JSF - Controle de acesso as páginas e componentes

Ae pessoal, boa tarde.

Estou desenvolvendo uma aplicação web onde eu uso JSF + Facelets + RichFaces e preciso controlar quais paginas um usuário possui acesso e além disso dentro de uma pagina quais os componentes da tela o usuario pode ver, por exemplo um usuario operacional pode entrar na tela de pedidos e ver a lista de pedidos e detalhar algum desses pedidos, mas o usuario administrativo pode criar um novo pedido, excluir um pedido existente, etc., ou seja, quero deixar visivel na pagina apenas o que o perfil do usuario pode ver.

Pesquisei na internet e utilizando faces eu vi que posso criar PhaseListener e antes da fase de RENDER_RESPONSE eu posso pegar o viewRoot e setar o rendered dos componentes para false, dessa forma ele não aparece na tela.
Também é possivel sobrescrever cada componente da tela e dentro do meu novo componente posso colocar o controle se mostro ou não o componente na tela, mas acho que dessa forma da mais trabalho.

Gostaria de saber se alguém ja fez algo parecido com isso e qual solução utilizou ?

Obrigado.

Bom dia!! Estou desenvolvendo um controle de perfil parecido com o seu!!! Porém, quando utilizo o método:

String currentPage = facesContext.getViewRoot().getViewId();

O valor que currentPage assume é o valor = “\home.jsp”, óbvio pois é de home que eu faço a requisição pelos menus para entrar nas telas do sistema.

Gostaria de saber como faço para para pegar o valor seguinte à home, por exemplo pegar “cadastro.jsp”, pois esse sim deve ter acesso restrito.

Se puder ajudar agradeço…

Oi dahenz,

Você só sabe qual página que será redirecionado depois que o ciclo de vida da requisição do faces passar pela fase INVOKE_APPLICATION.

Mas se você quer alterar a estrutura da arvore através do getViewId() para dar os rendered(false) nos componentes que não deve aparecer, você não vai conseguir, porque antes da fase RENDER_RESPONSE vc ainda não tem a estrutura da pagina que será exibida, e depois da fase RENDER_RESPONSE todas as alterações que você fizer não vão para a tela.

Valew rsakurai!!!

Só tenho mais uma dúvida, eu consigo pelo menos bloquear o acesso à página antes do RENDER_RESPONSE???

Se consigo… onde faço isso??? Obrigado pela ajuda…

Cria um PhaseListener, nele vc sobrescreve o método beforePhase() para a fase RENDER_RESPONSE e pega a pagina que ele esta querendo acessar, depois vc verifica se ele pode ou não ter esse acesso, caso ele não possa faz um redirect para alguma pagina de erro.

Alguem aqui conseguiu utilizar o PhaseListener?? Funcionou direitinho??

Na minha aplicação, depois que eu logo, se eu tentar acessar o banco postgres, tentar salvar algo no banco ou abrir outra jsp ele me joga na tela de login novamente. Alguem sabe me dizer o que é que está acontecendo??

Minha classe AuthorizationListener:

[code]package br.gov.rr.setrabes.util;

import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpSession;

import br.gov.rr.setrabes.estrutura.Usuario;

public class AuthorizationListener implements PhaseListener {

private static final long serialVersionUID = 1L;


public void afterPhase(PhaseEvent event) {
	System.out.println(event.getPhaseId());

	FacesContext facesContext = event.getFacesContext();
	String currentPage = facesContext.getViewRoot().getViewId();
	System.out.println("PAGINA DE DESTINO after: " + currentPage);


	boolean isLoginPage = (currentPage.lastIndexOf("login.jsp") < -1);
	HttpSession session = (HttpSession) facesContext.getExternalContext()
			.getSession(true);
	System.out.println("=======validado a página=======");
	Usuario currentUser = (Usuario) session.getAttribute("currentUser");

	if (!isLoginPage && currentUser == null) {
		NavigationHandler nh = facesContext.getApplication()
				.getNavigationHandler();
		System.out.println("<-------condicao lançada-------->");
		nh.handleNavigation(facesContext, null, "loginPage");
		System.out.println("<-------usuario nao logado-------->");
	} else {
		FacesContext.getCurrentInstance().getExternalContext()
				.getSessionMap().put("currentUser", currentUser);

		System.out.println("========leu o else=========");
	}
}

public void beforePhase(PhaseEvent event) {
	System.out.println("PRINT DE IDENTIFICAÇÃO DO EVENTO before: "
			+ event.getPhaseId());
}

public PhaseId getPhaseId() {
	return PhaseId.RESTORE_VIEW;
}

}[/code]

Minha jsp admin:

[code]<%@ taglib uri=“http://java.sun.com/jsf/core” prefix=“f”%>
<%@ taglib uri=“http://java.sun.com/jsf/html” prefix=“h”%>
<%@ taglib uri=“http://richfaces.org/a4j” prefix=“a4j” %>
<%@ taglib uri=“http://richfaces.org/rich” prefix=“rich” %>

Sistema de Gestão do Monitoramento e Avaliação dos Municípios - Modo Administrador !
<rich:tabPanel>
	<rich:tab label="Usuarios">
<h:form id="Cadastro">
	
	<h:outputText value="#{msgs['usuario-nome']}" />
	<h:inputText id="nome" required="true"
		value="#{usuarioHandler.usuario.nome}"
		validator="#{usuarioHandler.validaCase}">
		<f:validateLength minimum="5" />
	</h:inputText>
	<h:message for="nome" style="color: darkred" />
	<br />

	<h:outputText value="#{msgs['usuario-cpf']}" />
	<h:inputTextarea id="cpf" required="true"
		value="#{usuarioHandler.usuario.cpf}"> 
		<f:validateLength minimum="5" />
	</h:inputTextarea>
	<h:message for="cpf" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-rg']}" />
	<br />
	<h:inputTextarea id="rg"
		value="#{usuarioHandler.usuario.rg}" />
	<h:message for="rg" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-rg_exp']}" />
	<br />
	<h:inputTextarea id="rg_exp"
		value="#{usuarioHandler.usuario.rg_exp}" />
	<h:message for="rg_exp" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-endereco']}" />
	<br />
	<h:inputTextarea id="endereco"
		value="#{usuarioHandler.usuario.endereco}" />
	<h:message for="endereco" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-numero']}" />
	<br />
	<h:inputTextarea id="numero"
		value="#{usuarioHandler.usuario.numero}" />
	<h:message for="numero" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-bairro']}" />
	<br />
	<h:inputTextarea id="bairro"
		value="#{usuarioHandler.usuario.bairro}" />
	<h:message for="bairro" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-cidade']}" />
	<br />
	<h:inputTextarea id="cidade"
		value="#{usuarioHandler.usuario.cidade}" />
	<h:message for="cidade" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-cep']}" />
	<br />
	<h:inputTextarea id="cep"
		value="#{usuarioHandler.usuario.cep}" />
	<h:message for="cep" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-fone_residencial']}" />
	<br />
	<h:inputTextarea id="fone_residencial"
		value="#{usuarioHandler.usuario.fone_residencial}" />
	<h:message for="fone_residencial" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-fone_comercial']}" />
	<br />
	<h:inputTextarea id="fone_comercial"
		value="#{usuarioHandler.usuario.fone_comercial}" />
	<h:message for="fone_comercial" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-celular']}" />
	<br />
	<h:inputTextarea id="celular"
		value="#{usuarioHandler.usuario.celular}" />
	<h:message for="celular" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-cod_escolaridade']}" />
	<br />
	<h:inputTextarea id="cod_escolaridade"
		value="#{usuarioHandler.usuario.cod_escolaridade}" />
	<h:message for="cod_escolaridade" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-cod_cargo']}" />
	<br />
	<h:inputTextarea id="cod_cargo"
		value="#{usuarioHandler.usuario.cod_cargo}" />
	<h:message for="cod_cargo" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-funcao']}" />
	<br />
	<h:inputTextarea id="funcao"
		value="#{usuarioHandler.usuario.funcao}" />
	<h:message for="funcao" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-cod_lotacao']}" />
	<br />
	<h:inputTextarea id="cod_lotacao"
		value="#{usuarioHandler.usuario.cod_lotacao}" />
	<h:message for="cod_lotacao" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-cod_chs']}" />
	<br />
	<h:inputTextarea id="cod_chs"
		value="#{usuarioHandler.usuario.cod_chs}" />
	<h:message for="cod_chs" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-unidade']}" />
	<br />
	<h:inputTextarea id="unidade"
		value="#{usuarioHandler.usuario.unidade}" />
	<h:message for="unidade" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-login']}" />
	<br />
	<h:inputTextarea id="login"
		value="#{usuarioHandler.usuario.login}" />
	<h:message for="login" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-senha']}" />
	<br />
	<h:inputTextarea id="senha"
		value="#{usuarioHandler.usuario.senha}" />
	<h:message for="senha" style="color: darkred" />
	<br />
	
	<h:outputText value="#{msgs['usuario-nivel']}" />
	<br />
	<h:inputTextarea id="nivel"
		value="#{usuarioHandler.usuario.nivel}" />
	<h:message for="nivel" style="color: darkred" />
	<br />
	
	<h:commandButton value="Salvar" action="#{usuarioHandler.salva}" />
	
</h:form>	
<rich:spacer height="10"/>
<rich:separator height="1" lineType="dotted"/>
<rich:spacer height="10"/>

<jsp:include page="listauser.jsp" />
</rich:tab>
<rich:tab label="Cadastro Cargo">
	<jsp:include page="cargo.jsp"/>
</rich:tab>
<rich:tab label="Cadastro Carga Horaria Semanal">
	<jsp:include page="chs.jsp"/>
</rich:tab>
<rich:tab label="Cadastro Escolaridade">
	<jsp:include page="escolaridade.jsp"/>
</rich:tab>
<rich:tab label="Cadastro Lotacao">
	<jsp:include page="lotacao.jsp"/>
</rich:tab>
	
</rich:tabPanel>

</f:view>

[/code]

já usou JAAS?

Já li um pouco sobre ele, mas eu não queria fazer essa mudança drástica na minha aplicação já iniciada. E além disso, todos os tutoriais que eu vi sobre o JAAS não se usa o postgres.

Eu tenho encontrado muita dificuldade na resolução de problemas aqui no fórum. As pessoas visitam as páginas, mas não postam nada. Ou por falta de tempo, ou por falta de interesse em ajudar. Por isso, quero te agradecer por ter respondido.

Valeu.

Kleber-rr me add no msn: kafkapvh@hotmail.com email : web2ajax@gmail.com

[quote=rsakurai]

Mas se você quer alterar a estrutura da arvore através do getViewId() para dar os rendered(false) nos componentes que não deve aparecer, você não vai conseguir, porque antes da fase RENDER_RESPONSE vc ainda não tem a estrutura da pagina que será exibida, e depois da fase RENDER_RESPONSE todas as alterações que você fizer não vão para a tela.[/quote]

rsakurai, estou com esse mesmo problema. Quero fazer um controle de acesso a nível de componentes através do phase listener. Você conseguiu alguma coisa?

Minha solução para o problema:

Crie u Listner:

/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package br.cep.filter;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpSession;

/**
*

  • @author joao
    */
    public class AuthorizationListener implements PhaseListener {

    // REPRESENTA A LISTA DE PÁGINA QUE O USUÁRIO PODE ACESSAR
    private String[] paginasAutorizadas = new String[]{"/jsp/login.xhtml", “/jsp/dashBoard.xhtml”, “/jsp/consultarCliente.xhtml”};

    //RESPONSÁVEL POR VERIFICAR SE O USUÁRIO ESTA AUTORIZADO
    public boolean verificarAutorizacao(String paginaRequisitada) {
    /*
    for (String pagina : paginasAutorizadas) {
    if (paginaRequisitada.equals(pagina)) {
    return true;
    }
    }
    return false;
    *
    */
    return true;
    }

    /**

    • Método chamado sempre apósa execução de uma determinada PHASE

    • @param event - {@link PhaseEvent}
      */
      public void afterPhase(PhaseEvent event) {
      boolean Logado = false;
      System.out.println(event.getPhaseId());
      FacesContext ctx = event.getFacesContext();

      if (ctx.getViewRoot() == null) {
      try {
      ctx.getExternalContext().redirect("/Endereco/");
      } catch (IOException ex) {
      Logger.getLogger(AuthorizationListener.class.getName()).log(Level.SEVERE, null, ex);
      }
      } else {
      String paginaDestino = ctx.getViewRoot().getViewId();
      System.out.println(paginaDestino);

       //CONFORME DITO ANTERIORMENTE MESMO SEM O USO DE NA FASE
       // APPLY_REQUEST_VALUES O NOME DA PÁGINA ESTARA ATUALIZADO, PORTANTO E
       //NESSA FASE QUE PODEMOS VERIFICAR SE O USUÁRIO ESTA AUTORIZADO A ACESSAR
       //A PÁGINA REQUISITADA
       //  if (event.getPhaseId().equals(PhaseId.APPLY_REQUEST_VALUES)) {
       ctx = event.getFacesContext();
       //CAPTURA O USUÁRIO LOGADO POIS SE ESTA FASE FOR EXECUTADA SIGNIFICA QUE EXISTE USUÁRIO AUTENTICADO
       HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
       Object usuarioLogado = session.getAttribute("currentUser");
       if (usuarioLogado != null) {
           Logado = true;
       }
       String urlDestino = ctx.getViewRoot().getViewId();
       boolean isLoginPage = (urlDestino.lastIndexOf("login.jsp") > -1);
      
       //VALIDA A AUTORIZAÇÃO PARA ACESSAR A PÁGINA
       if (!Logado && !isLoginPage) {
           NavigationHandler nh = ctx.getApplication().getNavigationHandler();
           nh.handleNavigation(ctx, null, "loginPage");
       }
      

      }
      }

    /**
    ** Método chamado sempre antes de se executar uma determinada PHASE

    • @param event - {@link PhaseEvent}
      /
      public void beforePhase(PhaseEvent event) {
      /

      System.out.println(event.getPhaseId());
      FacesContext ctx = event.getFacesContext();
      String paginaDestino = ctx.getViewRoot().getViewId();
      System.out.println(paginaDestino);

      if (event.getPhaseId().equals(PhaseId.RESTORE_VIEW)) {
      //AQUI DEVE FICAR A LÓGICA PARA VERIFICAR SE EXISTE UM USUÁRIO
      //AUTENTICADO NA APLICAÇÃO
      ctx = event.getFacesContext();
      //verifica se existe um usuário autenticado
      HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
      if (session.getAttribute(“usuarioLogado”) == null) {
      try {
      //se não existir direciona para a página de LOGIN
      ctx.getExternalContext().redirect("/pages/login/login.jsp");
      } catch (IOException ex) {
      Logger.getLogger(AuthorizationListener.class.getName()).log(Level.SEVERE, null, ex);
      }
      }
      }
      *
      */
      }

    /**

    • Retorna o PhaseId da fase do ciclo de vida JSF que
    • esta sendo interceptado e gerênciado pelo Controle de acesso.
    • @return - {@link PhaseId}
      */
      public PhaseId getPhaseId() {
      //return PhaseId.ANY_PHASE;
      return PhaseId.RESTORE_VIEW;

    }
    }

Configure seu faces-config.xml:

/* loginPage /pages/login/login.jsp br.cep.filter.AuthorizationListener java.lang.NullPointerException /pages/login/login.jsp

Ele pega a session da aplicação e vai para a pagina do Login ok.

Abraços

Jomello