Duvida em componentes JSF

23 respostas
rbroz85

Bom dia,

Estou com uma duvida, que na verdade nem é duvida… eu não estou conceguindo fazer mesmo!
entao:
eu tenho um pagina no qual apresenta alguns botoes. que levam a certas paginas do sistema.
no entanto se for usuario comum. alguns desses botoes nao podem aparecer para ele !
no meu managedBean eu tenho: String adm = 0 ( para usuario ) e adm = 1 (para administrador)

como posso fazer os botoes sejam respectivos para os tipos de usuario (0) ou (1)?
e como posso testar se o usuario é do tipo (1) se entrar em uma pagina que nao deve? e redirecionalo para outra

estou usando jsp com sintaxe xml, jspx, e usando o icefaces.

bem sinceramente nao estou conceguindo fazer isso. o sistema esta pronto so esta dependendo disso!
se alguma boa alma rs poder me dar o caminho das pedras? mt grato desde já

abraços a todos

23 Respostas

Luiz_Gustavo

Olá

Então… algumas observações e sugestões sobre o que você relatou.

Imagino que você tenha um atributo para o usuário que identifique o tipo do mesmo, e que, após o login, você mantenha uma instância de um objeto “Usuário” na sessão, para consultar esse atributo.
Você poderia colocar a propriedade “rendered” desses botões de acordo com o estado desse atributo da instância de um “Usuário”. Essa seria uma forma de fazer esse controle.
Agora tenho uma pergunta: O usuário conseguiria acessar uma página, mesmo que não tenha acesso à mesma, através da URL, digitando diretamente o caminho para tal página?
Uma forma legal de controlar acesso é usar o próprio container para fazer o controle, através de ROLES. Ex:

<login-config>
  <auth-method>FORM</auth-method>
  <form-login-config>
   <form-login-page>/login.jsp</form-login-page>
   <form-error-page>/loginInvalido.jsp</form-error-page>
  </form-login-config>
 </login-config>
 <!-- ROLES -->
 <security-role>
  <role-name>administrador</role-name>
 </security-role>
 <security-role>
  <role-name>educador</role-name>
 </security-role>
 <security-role>
  <role-name>gerente</role-name>
 </security-role>
 <security-role>
  <role-name>consultor</role-name>
 </security-role>

No exemplo acima, tenho os ROLES administrador, educador, gerente e consultor.
Com isso pode-se definir o que um usuário de determinado ROLE poderá acessar, através de constraints:

<security-constraint>
  <web-resource-collection>
   <web-resource-name>Páginas de Acesso Restrito a Educadores, Administradores e Gerentes</web-resource-name>
   <url-pattern>/educ/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>administrador</role-name>
   <role-name>educador</role-name>
   <role-name>gerente</role-name>
  </auth-constraint>
 </security-constraint>

tudo isso configurado no próprio web.xml.

Alguns componentes, como o tomahawk, permitem um controle utilizando esses ROLES, ex:

<x:navigationMenuItem id="cadAtivid" itemLabel="#{msg.lblMenuAtivid}" action="#{atividadeFace.listAtividades}" visibleOnUserRole="administrador, gerente"/>

dessa forma o controle é feito automaticamente de acordo com o ROLE do usuário logado.

Espero ter ajudado, e me desculpe se chovi no molhado em algum momento!

rbroz85

Brother voce chuveu exatamento no deserto, onde tava mais precisando… rs
isso é exatamento o que eu queria…

sim eu tenho um obj usuario em session. com atributo ADM ou é 1para adm ou 0 para user.

agora como vou fazer esses roles para o login? nem sei por onde começar !

Luiz_Gustavo

Aqui estão algumas fontes de informação que podem ajudar:

http://tomcat.apache.org/tomcat-4.1-doc/realm-howto.html
http://www.linux-sxs.org/internet_serving/c619.html
http://java.sun.com/javaee/5/docs/tutorial/doc/Security-Intro6.html

[]'s

rbroz85

valeu meu camarada. obrigado ae pela atençao e ajuda.
vou dar uma estudada!
mt obrigado mesmo!
grande abraço

rbroz85

como eu digo pro web.xlm o tipo do usuario que esta logado ?

meu managedBean do login esta assim:

public String doLogin(){
        boolean noblan = true;
        boolean ok = false;
        String msg = "";
        FacesContext context = FacesContext.getCurrentInstance();
        
        if(login.equals("")||pword.equals("")){
            msg = "Todos campos devem ser preenchidos.";
            noblan = false;
        }   
        if(noblan){
            ok = haveLogin(login,pword);
            if(ok==false)
                msg = "Login ou Senha Invalidos.";
        }          
        FacesMessage message = new FacesMessage(msg);
        context.addMessage("formlogin:errMsg", message);
        
        return (ok ? "main" : "nologin");
    }

    public boolean haveLogin(String login,String pword){
        boolean ok = false;
        LoginBean lo = new ConsultaLogin().haveLogin(login);
        System.out.println("> "+lo.getLogin()+", > "+lo.getPword());
        if(lo.getLogin()!=null&&lo.getPword()!=null)
            if(lo.getLogin().equals(login)&&lo.getPword().equals(pword))
                ok = true;
                
       if(ok){
            this.login = lo.getLogin();
            this.pword = lo.getPword();
            this.adm = lo.getAdm();
        }
       return ok; 
    }

nao entendi como eu digo pro web.xml quem ´quem, onde eu digo isso ?

Luiz_Gustavo

Opa,

como comentei contigo por e-mail, estou de volta pra dar mais algumas informações a respeito da sua dúvida.
Vou tentar colocar uma visão geral de como esse esquema de permissão funciona. Maiores detalhes você pode encontrar no link: http://tomcat.apache.org/tomcat-4.1-doc/realm-howto.html , que eu postei antes.

Na verdade quem vai fazer a validação e descobrir que tipo de usuário está acessando a página é o próprio container.
Você precisa ter uma tabela adicional no seu banco, relacionada (não necessariamente com chaves estrangeiras ) com a tabela de usuários. Essa tabela vai guardar as informações dos perfis de seus usuários (ROLES). Um exemplo dessa tabela é dada no exemplo da página que lhe passei:

create table users (
  user_name         varchar(15) not null primary key,
  user_pass         varchar(15) not null
);

create table user_roles (
  user_name         varchar(15) not null,
  role_name         varchar(15) not null,
  primary key (user_name, role_name)
);

A tabela “user_roles” é que vai guardar a informação do perfil (ou perfis, se um usuário puder ter mais de um) de seus usuários.

Com relação às configurações:

Exemplos:

web.xml


<!-- RESTRIÇÕES DE SEGURANÇA (aqui você indica quem pode acessar o quê)-->
 <security-constraint>
  <web-resource-collection>
   <web-resource-name>Páginas de acesso restrito a Administradores</web-resource-name>
   <url-pattern>/admin/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>administrador</role-name>
  </auth-constraint>
 </security-constraint>
 <security-constraint>
  <web-resource-collection>
   <web-resource-name>Páginas de acesso acesso Restrito a Educadores, Administradores e Gerentes</web-resource-name>
   <url-pattern>/educ/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>administrador</role-name>
   <role-name>educador</role-name>
   <role-name>gerente</role-name>
  </auth-constraint>
 </security-constraint>
 <security-constraint>
  <web-resource-collection>
   <web-resource-name>Páginas de Acesso Restrito a Administradores e Gerentes</web-resource-name>
   <url-pattern>/manag/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>administrador</role-name>
   <role-name>gerente</role-name>
  </auth-constraint>
 </security-constraint>
  <security-constraint>
  <web-resource-collection>
   <web-resource-name>Paginas de Acesso Comum</web-resource-name>
   <url-pattern>/common/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>administrador</role-name>
   <role-name>gerente</role-name>
   <role-name>consultor</role-name>
   <role-name>educador</role-name>
  </auth-constraint>
 </security-constraint>
 
 
 <!-- MÉTODO DE LOGIN PARA VALIDAÇÃO DE ACESSO (aqui você indica o método de validação. use FORM para que você possa usar um formulário criado por você mesmo, e indique as páginas desse formulário, e uma para possível erro de login)-->
 <login-config>
  <auth-method>FORM</auth-method>
  <form-login-config>
   <form-login-page>/login.jsp</form-login-page>
   <form-error-page>/loginInvalido.jsp</form-error-page>
  </form-login-config>
 </login-config>
 
 
 <!-- ROLES (esses são os possíveis perfis de usuário do seu sistema)-->
 <security-role>
  <role-name>administrador</role-name>
 </security-role>
 <security-role>
  <role-name>educador</role-name>
 </security-role>
 <security-role>
  <role-name>gerente</role-name>
 </security-role>
 <security-role>
  <role-name>consultor</role-name>
 </security-role>
 
 
 
  <!-- Welcome files (após a validação de acesso, o container saberá para onde direcionar o usuário, através dessa relação de páginas) -->
 <welcome-file-list>
  <welcome-file>index.jsf</welcome-file>
  <welcome-file>index.jsp</welcome-file>
  <welcome-file>index.html</welcome-file>
 </welcome-file-list>

Na página que você indicar para o método de login (no caso do exemplo login.jsp) lembre-se de colocar as seguintes informações, que serão usadas pelo container para identificar o que é nome de usuário e senha. O action “j_security_check” é importante para que se saiba que é o container que vai efetuar a validação, o campo com nome “j_username” indica qual é o campo que contém o nome de usuário e o campo “j_password” a senha:

<form method="post" action="j_security_check">

	...
	<input size="20" name="j_username" class="text">
	...
	<input type="password" size="10" name="j_password" class="text">
	...
</form>

No server.xml você define um Resource para o seu banco:

server.xml 
 
 
 <GlobalNamingResources> 
 ... 
 <Resource auth="Container" driverClassName="org.gjt.mm.mysql.Driver" 
 	maxActive="30" maxIdle="10" maxWait="-1" name="jdbc/nome_data_source" 
 	password="senha_usuario_banco" type="javax.sql.DataSource" 
 	url="jdbc:mysql://localhost:3306/nome_banco" 
 	username="nome_usuario_banco"/> 	
...
 </GlobalNamingResources>

e um REALM

<Realm className="org.apache.catalina.realm.DataSourceRealm" 
 	connectionName="nome_usuario_banco" connectionPassword="senha_usuario_banco" 
 	connectionURL="jdbc:mysql://localhost:3306/nome_banco" dataSourceName="jdbc/nome_data_source" 
 	debug="5" driverName="org.gjt.mm.mysql.Driver" 
 	roleNameCol="use_rolename" userCredCol="use_password" userNameCol="use_name" 
 	userRoleTable="user" userTable="user"/>

ps: observe que o REALM faz referência ao Resource declarado anteriormente: dataSourceName=“jdbc/nome_data_source” .

O REALM possui atributos que permitem identificar as tabelas e campos necessários para identificar o usuário e seu ROLE (ou ROLES):

roleNameCol - A coluna que contém o nome do ROLE
userCredCol - A coluna que possui a senha
userNameCol - A coluna que possui o nome de usuário
userRoleTable - A tabela que possui os ROLES
userTable - A tabela de usuários

alí no exemplo que coloquei, eu usei a mesma tabela de usuário para guardar a informação de ROLE, uma vez que nesse sistema em questão um usuário tem somente um tipo de acesso.
Se for pelo exemplo de colunas que postei no início, essa configuração seria a seguinte (referente a tabelas e campos):

<Realm className="org.apache.catalina.realm.DataSourceRealm" debug="99"
   dataSourceName="java:/comp/env/jdbc/authority"
   userTable="users" userNameCol="user_name" userCredCol="user_pass"
   userRoleTable="user_roles" roleNameCol="role_name"/>

ps: Observe que nos casos acima, o tipo de REALM utilizado é “DataSourceRealm”. Na página que te passei há explicação específica para esse tipo de REALM.

para definir o ROLE, o container busca na tabela de ROLES um ROLE que atenda ao nome de usuário informado.

Bem, espero ter esclarecido um pouco mais.

Abraços e boa sorte!

thigo.san

Luiz Gustavo, eu te ajudo com o JBoss e voce me ajuda com o JSF. Eu tenho numa página de cadastro um botão que abre um popup para fazer buscas. Quando eu entro pela primeira vez na tela de busca, eu consigo entrar buscar o que eu quero e retornar, porém se eu já fiz uma vez a busca e vou entrar denovo, a aplicação não acha mais meu popup por causa da URL que fica zoada. Eu falei com um pessoal, e eles falaram que era porque o “method” da página estava como GET, e falaram pra eu colocar como POST. Sabe como eu faço isso em JSF, ou tem alguma outra solução? Desde já agradeço.

Luiz_Gustavo

Opa, falaí maninho!!

Eu fiz um esquema de busca usando pop-up.
Ao invés de um botão, coloquei um link (para poder usar uma imagem e conseguir setar um target) e o action deste link estava vinculado a uma ação no backbean.
Porém, no onclick do link eu crio uma página pop-up, com as dimensões e tudo mais, e dou um nome a ela, e coloco como target essa página (usando o nome dado).
Então no método referenciado no action, eu retorno o nome da página que é para ser apresentada no pop-up (a página de busca).
Essa é a primeira parte :smiley:
Depois, nesta página de busca, cada item apresentado no grid é um link, com um parâmetro referenciando o id do que eu quero pesquisar. O action deste link referencia um método no backbean que, usando o parâmetro passado, localiza o registro. o retorno deste método é o nome da primeira página.
Agora, para que a primeira página não seja apresentada no pop-up, no link da página de busca eu coloco, no onclick, uma camada javascript para fechar a janela, e no target eu referencio a página que a chamou.
Para referenciar, na página do pop-up, a janela que chamou o pop-up, vc declara o atributo “opener” da página (se não me engano é isso :D), setando pra ele um nome, e usa esse nome no target.

Espero que tenha ajudado.

É que não tenho os códigos aqui, mas qualquer coisa na segunda-feria posto aqui :smiley:

Abraços!

thigo.san

Voce esclareceu algumas coisas, bom a parada do window.opener eu já consegui fazer, só que o problema é que eu não estou conseguindo passar para a minha função javascript o valor do commandLink. A minha função funciona, só que ele manda lá pro campo na outra página o valor “undefined”. Bom eu to fazendo da seguinte forma:

Esse é o meu dataTable:

<h:dataTable border="0" id="table" var="currency" rendered="#{! empty seaCurrencyMB.listDtmMdlCurrency}" value="#{seaCurrencyMB.listDtmMdlCurrency}" styleClass="tabelaDadosGC"> <h:column> <f:facet name="header"><h:outputText value="#{c.crc_uid}"/></f:facet> <h:outputText value="#{currency.currencyUid}"/> </h:column> <h:column> <f:facet name="header"><h:outputText value="#{c.crc_code}"/></f:facet> <h:commandLink value="#{currency.currencyCode}" onclick='selectedCode(this.textContent)'/> </h:column> <h:column> <f:facet name="header"><h:outputText value="#{c.crc_name}"/></f:facet> <h:outputText value="#{currency.currencyName}"/> </h:column> </h:dataTable>

Esse é a minha função javascript, com alguns alert`s:

function selectedCode(td){  
			alert(td.tagName);
			alert(td.nodeName);			
			window.opener.document.getElementById('form1:currencycode').value = td.text;
			self.close();
		}
Javabuntu

Luiz_Gustavo …

aproveitando suas dicas, eu consigo implementar essa autenticação feita no xml no jboss?? ou dessa maneira somente tomcat…??

thigo.san

No jboss, tem como voce configurar os usuários do banco de dados e também da página de administração do servidor. Seria isso, ou voce quer usar usuário e senha do sistema num xml do jboss. Se for isso até teria como, mas não seria muito recomendável por motivos de segurança.

Luiz_Gustavo

Falaí maninho, tudo jóia?

Estou postando os exemplos do esquema do pop-up.

Este é o trecho da página principal, que chama o pop-up:

<td align="left">
	<h:commandLink value="" onclick="javascript:window.open('','buscaCliOc','height=350,width=640,toolbar=no,scrollbars=no')" target="buscaCliOc" action="#{ocorrenciaAtividadeFace.abrirPesquisaClientes}">
		<t:graphicImage url="/images/lupa.jpg" border="0"/>												
	</h:commandLink>
</td>

É criado o pop-up e ele é o target do link. O método “abrirPesquisaClientes” se encarrega de retornar o nome do arquivo xhtml (no meu caso) que contém a página de busca a ser mostrada no pop-up, nome este que se encontra mapeado para a página xhtml no faces-config.xml

O script seguinte fica no head da página pop-up, e é responsável por dar um nome à página que chamou o pop-up:

<script type="text/javascript">
	window.opener.name = 'clienteOcorrencia';
</script>

Esta é a coluna do dataTable que está na página de pop-up. Nela há um link responsável por selecionar o cliente, e o target é a página que chamou o pop-up. Repare que no evento onclick a janela pop-up é fechada.

<h:column>
	<f:facet name="header">
		<h:outputText value="#{msg.lblColumnNome}"/>
	</f:facet>
	<a4j:htmlCommandLink value="#{client.peoName}"  target="clienteOcorrencia" onclick="javascript:window.close()" action="#{ocorrenciaAtividadeFace.selecionarCliente}" limitToList="false">
		<f:param value="#{client.peoId}" name="cliID"/>			            				
	</a4j:htmlCommandLink>
</h:column>

o método “selecionarCliente” retorna o nome lógico da página principal.

Espero que tenha ajudado!!

Abraços!

Luiz_Gustavo

Javabuntu:
Luiz_Gustavo …

aproveitando suas dicas, eu consigo implementar essa autenticação feita no xml no jboss?? ou dessa maneira somente tomcat…??

Falaí maninho, beleza?

Olha, com o Jboss eu nunca cheguei a testar, mas acredito que funcione sem problema algum, pois o servlet container dele é o tomcat.

abraços!

Javabuntu

Javabuntu:
Luiz_Gustavo …

aproveitando suas dicas, eu consigo implementar essa autenticação feita no xml no jboss?? ou dessa maneira somente tomcat…??


pelo que li… o conteiner se responsabiliza por verificar se o usuário possui autorização de acordo com tabela user X role…
1- ele se encarrega de colocar na sessão também ou preciso tratar isso??

2- vi que no xml tem umas propriedades pra direcionar se o login foi ok ou incorreto:

<login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login.jsp</form-login-page> <form-error-page>/loginInvalido.jsp</form-error-page> </form-login-config> </login-config>
nesse caso tenho 2 opções, certo ou incorreto…e as respectivos direcionamentos…

como faço pra dizer se for OK, dependente do tipo de role, tipo:
role= admin vai admin.jsp
role = user vai user.jsp
role = xpto vai para outra.jsp

tem como tratar isso no web-xml…não? onde seria?

3- se um usuário possuir várias roles, tipo usuário Joãzinho tem roles admin, user, gerente…
tem como DEPOIS de logado, eu mudar o tipo de perfil pra renderizar as informações e SEM fazer logout??

desculpe pessoal, pesquisei muito mas não consegui respostas pra isso, a quem ajudar nestas 3 questões ficarei muito grato…

Luiz_Gustavo

Opa, bom dia! (boa madrugada nesse exato momento)

Quando você utiliza este tipo de autenticação, é disponibilizado no request (HttpServletRequest) um objeto de uma classe que implementa Principal (java.security.Principal).
Através dela é possível obter o nome do usuário logado (o username usado).

Com essa informação você consegue obter da sua base de dados os demais dados do seu usuário, fazendo, por exemplo, uma consulta à tabela:

// User é um objeto do meu domínio de negócio
User user = null;

// java.security.Principal
Principal userPrincipal;
		
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
		
userPrincipal = request.getUserPrincipal();     

// uma factory de objetos de negócio.... específico do domínio da aplicação
BusinessFactory bf = BusinessFactory.getInstance();

// objeto de negócio que fará a consulta por um usuário do meu sistema
UserBO bo = bf.getUserBO();

// obtenho um usuário do meu sistema através da informação obtida do Principal...
user = bo.getByUseName(userPrincipal.getName());

Pelo que sei não tem como relacionar uma página inicial para cada Role.
O que você pode tentar fazer é criar uma página inicial de acesso comum a todos os Roles, e nele colocar links para acessar as páginas iniciais para cada perfil, optando por mostrar ou não esses links de acordo com o tipo de usuário logado.

Usando a dica do primeiro caso, de obter o usuário da base de dados de acordo com o nome, você poderia já carregar para seu objeto usuário uma coleção de todos os Roles que ele tem, e usar essas informações para renderizar o que for necessário para ele.
Você não precisa (se bem que pode) escolher uma ou outra Role se o usuário tiver mais de uma, escolha todas de uma vez e tenha essas informações em mãos, afinal, se o usuário possui mais de uma ele deveria desfrutar dos privilégios que elas garantem a ele ao usar o sistema. Mas isso já é específico de cada aplicação :wink:

Bom, espero ter ajudado.
Peço desculpas pela demora da resposta.

Qualquer coisa posta aqui novamente.

Abraços!

Jux

Luiz Gustavo,

Se eu estivesse criando uma aplicação que as roles fossem dinâmicas, ou seja, o portal tivesse a funcionalidade de criar perfis na aplicação, como eu poderia adicionar essas novas roles no web.xml, e usar o JSF ao mesmo tempo.

Junior

Jux

Luiz Gustavo você poderia postar um exemplo completo ou me mandar por e-mail essa implementação de autorização com jsf. Eu já estou há duas semanas tentando fazer isto.

meu e-mail é [email removido]

Valeu

Junior

balthazar

Ola para todos!
Esse topico ja tem um e não sei se alguem ainda ta frequentando. Bom, notei que o Jux estava negociando um projeto teste com o Luiz Gustavo referente a autorização com jsf, bem eu estou tendo alguns problemas serios com isso tambem e gostaria , se possivel logico, que voces compartilhasem desse exemplo com migo, eu agradeço muito se puderem me ajudar pos os post estão muito bons mesmo.

meu email é [email removido]

att,

D

Luiz_Gustavo:
Opa,
Na verdade quem vai fazer a validação e descobrir que tipo de usuário está acessando a página é o próprio container.
Você precisa ter uma tabela adicional no seu banco, relacionada (não necessariamente com chaves estrangeiras ) com a tabela de usuários. Essa tabela vai guardar as informações dos perfis de seus usuários (ROLES). Um exemplo dessa tabela é dada no exemplo da página que lhe passei:

Encontrei este mesmo exemplo em um blog.

Mas me diga, como posso fazer logoff do usuário.
Um session.invalidate(); neste caso geraria um NullPointerException, e eu quero fazer isso em uma classe Java e não em um Servlet. Pretendia criar uma classe pra servir de Bean, pois só quero utilizar JSF pra isso e não Servlets.

Obrigado.

D

Também achei duas falhas: após um login inválido, onde mostra a url verdadeira da página de login e logo depois um login correto, redireciona pra página login.jsp novamente, apesar de o diretório não ter esta página, pois é uma página única, onde servirá pra logar em qualquer diretório e seus subdiretórios, o que resultará em página não encontrada.

Após o login dá pra acessar os outros diretórios de outros administradores e olha que eu configurei pra ter um editor e um administrador.
Como corrigir isso.

D

*edit, não tem problema nenhum.
Confundi =/
desculpe e obrigado. ^^

[]s

Marques

Se possível eu também gostaria de receber o exemplo.
Meu email: [email removido]

Sds,

Marques

C

Marques:
Se possível eu também gostaria de receber o exemplo.
Meu email: [email removido]

Sds,

Marques

Claro.

O link é esse aqui:

Lá eu resolvo o problema que tive quando tentei validar um usuário com JSF.

Abraços e tomara que se saia bem! :slight_smile:

Até.

Criado 22 de agosto de 2007
Ultima resposta 6 de abr. de 2009
Respostas 23
Participantes 9