Login aplicação JSF - [Resolvido]

Olá a todos, eu sei q vcs vão querer me bater por criar mais um tópico desses, mas o fato é q eu já li vários tópicos, tutoriais, e ainda não consegui entender, ou melhor, até consegui entender vários deles, mas não sei se é exatamente o q eu procurava, então acabei não conseguindo implementar minha idéia…

Bom, eu terei mais páginas no site, mas por enquanto tenho a index.xhtml e a enviarPromocoesCliente.xhtml, eu ja implementei várias coisas, mas to apanhando nesse login…

A idéia é a seguinte, a pagina inicial, qualquer pessoa podera acessar, é uma pagina que por hora vai exibir um catalogo de promoções do mês ou uma lista de produtos que o usuario pesquisou através de filtros disponíveis… Já a pagina enviarPromocoesCliente.xhtml, somente quem fizer login poderá acessar… Abaixo vou relacionar o que eu já fiz, e o que eu nao sei fazer:

Parte que interessa referente ao login, na index.xhtml<p:outputPanel> <h:outputText value="Nome:"/> <p:inputText value="#{mBUsuarioLogado.nome}" /> <h:outputText value="Senha:" /> <p:password value="#{mBUsuarioLogado.senha}" feedback="false" minLength="3"/> <p:commandButton value="Logar" action="#{mBUsuarioLogado.login()}" update="messages,pgLogin" style="font-family: Tahoma;font-size: 10px"/> </p:outputPanel>Abaixo o MB que verifica o usuario e mantém um objeto usuarioLogado com o carinha que logou[code]@ManagedBean
@SessionScoped
public class MBUsuarioLogado {

private DAO dao = DAO.getInstance();
private HibernateUtil hu = new HibernateUtil();

private List<Usuarios> usuarios = new ArrayList<Usuarios>();
private Usuarios usuarioLogado;

private String nome;
private String senha;

//construtor, sets e gets

public void login() {
    boolean nomeOk = false;
    boolean senhaOk = false;
    
    usuarioLogado = null;
    usuarios.clear();
    
    Criteria c = hu.getCriteria(Usuarios.class);
    usuarios = dao.listarCriteria(c);
    
    for (Usuarios u : usuarios) {
        if (u.getNome().equals(nome)) {
            nomeOk = true;
            if (u.getSenha().equals(senha)) {
                senhaOk = true;
                usuarioLogado = u;
            }
            break;
        }
    }
    
    if (!nomeOk) {
        FacesMessage error = new FacesMessage("Falhou", "Nome incorreto !");
        FacesContext.getCurrentInstance().addMessage(null, error);
    }
    if (!senhaOk) {
        FacesMessage error = new FacesMessage("Falhou", "Senha incorreta !");
        FacesContext.getCurrentInstance().addMessage(null, error);
    }
    if (nomeOk && senhaOk) {
        FacesMessage msg = new FacesMessage("Login OK", usuarioLogado.getNome());
        FacesContext.getCurrentInstance().addMessage(null, msg);
    }
    
    nome = "";
    senha = "";
}

public void logout() {
    usuarioLogado = null;
}

}[/code]E agora ? eu nao sei continuar daqui… O que eu tenho q fazer para que, somente quando alguem tente acessar a pagina enviarPromocoesCliente.xhtml, seja verificado se existe um usuario logado ?

Desculpe a nubice ae pessoal, é q tenho pouca experiencia na web, e to apanhando há 3 dias desse login… hahaha

Desde já grato ! t+

Bom dia,

Da uma estudada sobre JAAS, creio que será util.

Tem um artigo aqui no GUJ sobre o assunto… http://www.guj.com.br/articles/184

eu ja tinha olhado rapido JAAS, vou dedicar mais tempo agora pra ele, qq coisa volto a postar ai, obrigado t+

Minha sugestão é utilizar um framework especializado em autenticação/autorização.
O JAAS citado anteriormente é um deles.
Aqui tem um exemplo usando JSF + Spring Security

Creio que vc deve fazer o contrário: ao invés de pegar todos os usuarios do BD e comparar com o usuario do MB,vc deve fazer um ‘find’ no banco com os dados que vieram da tela.

Sobre o login,eu faço com Filter e fica show de bola.

sei lá, posso estar enganado, mas me parece muita coisa pra fazer um simples controle de acesso, nao tem nd mais simples, sei lá, aquelas navigation rules, filters… ?

opa raf4ever, blz? então, eu acho q filters vai ser mais simples…

a questão de buscar todos os usuarios, é só pra informar se o nome esta errado ou a senha, é frescura do pessoal aqui… no inicio eu tinha feito como vc falou, e como não terão muitos usuários mesmo, concordei em fazer a consulta dessa forma…

mas eu nao sei fazer esses filters, será q vc ou alguem que esteja lendo ai, poderia dar um exemplo ? ou tutorial que explique direito, pq eu até ja vi vários exemplos na net, mas sempre só tem o código fonte, e eu acabo não entendendo…

vlw t+

Filter,meu caro…

Olha esse meu exemplo:

public class LoginFilter implements Filter {
	@Override
	public void init(FilterConfig arg0) throws ServletException {}
	@Override
	public void destroy() {}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		try{
			HttpServletRequest httpReq = (HttpServletRequest)req;
			HttpServletResponse httpRes = (HttpServletResponse)res;
			HttpSession session = httpReq.getSession(true);
			if(session.getAttribute("usuario")==null 
					&& !httpReq.getRequestURL().toString().contains("login.jsf")
					&& !httpReq.getRequestURL().toString().endsWith(".css")
					&& !httpReq.getRequestURL().toString().endsWith(".js")
					&& !httpReq.getRequestURL().toString().endsWith(".jpg")
					&& !httpReq.getRequestURL().toString().endsWith(".gif")){
				httpRes.sendRedirect(httpReq.getContextPath()+"/login.jsf");
			}else{
				chain.doFilter(req, res);
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}

nao vai, kkkkkk olha só, eu fiz o seguinte:[code]public class FiltrarRestricoes implements Filter, Serializable {

private FilterConfig fc;

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    fc = filterConfig;
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    HttpSession session = req.getSession(true);
    String paginaRequisitada = req.getRequestURL().toString();
    
    Usuarios usuario = (Usuarios) session.getAttribute("usuarioLogado");        
    System.out.println("pegou o usuario " + usuario.getNome());
    if (usuario == null && !paginaRequisitada.contains("index.xhtml")) {
        System.out.println("redirecionou para pagina index");
        resp.sendRedirect("index.xhtml");
    } else {
        System.out.println("redirecionou para pagina" + paginaRequisitada);
        chain.doFilter(request, response);
    }
}

@Override
public void destroy() {
    
}

}[/code]e no web.xml eu coloquei:<filter> <filter-name>area restrita</filter-name> <filter-class>controle.FiltrarRestricoes</filter-class> </filter> <filter-mapping> <filter-name>area restrita</filter-name> <url-pattern>/enviarPromocoesCliente.xhtml</url-pattern> </filter-mapping>a parte de login na index e verificação de usuario no banco continua igual o primeiro post. quer dizer tem uma diferencinha no método login() do MBUsuarioLogado.[code]public void login() {
boolean nomeOk = false;
boolean senhaOk = false;

    usuarioLogado = null;
    usuarios.clear();
    
    Criteria c = hu.getCriteria(Usuarios.class);
    usuarios = dao.listarCriteria(c);
    
    for (Usuarios u : usuarios) {
        if (u.getNome().equals(nome)) {
            nomeOk = true;
            if (u.getSenha().equals(senha)) {
                senhaOk = true;
                usuarioLogado = u;
            }
            break;
        }
    }
    
    HttpSession ses = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
    ses.removeAttribute("usuarioLogado");
    if (!nomeOk) {
        FacesMessage error = new FacesMessage("Falhou", "Nome incorreto !");
        FacesContext.getCurrentInstance().addMessage(null, error);
    }
    if (!senhaOk) {
        FacesMessage error = new FacesMessage("Falhou", "Senha incorreta !");
        FacesContext.getCurrentInstance().addMessage(null, error);
    }
    if (nomeOk && senhaOk) {
        FacesMessage msg = new FacesMessage("Login OK", usuarioLogado.getNome());
        FacesContext.getCurrentInstance().addMessage(null, msg);
                    
        ses.setAttribute("usuarioLogado", usuarioLogado);
        
        System.out.println("logou usuario " + usuarioLogado.getNome());
    }
    
    nome = "";
    senha = "";
}[/code] agora eu coloco o usuario na httpsession. Mas se eu tento acessar a pagina restrita, ele acessa normal, nem verifica nd, nao executa o metodo doFilter(...), os System.out ali nao sai nenhum no console... tah faltando alguma coisa?

falta alguma coisa ? fiz algo errado ? alguem tem ideia do pq nao funciona ?

cara eu me bati com o Filter ai usei o PhaseListener muito bom para aplicações pequenas

então Polverini, pelo q eu vi, o phaselistener vai fazer a validação em todos os acessos, em todas as paginas não é ? ou eu estou enganado, pelo menos eu nao vi onde definir isso, eu quero apenas fazer validação de usuario em determinadas paginas, por isso achei o filter mais facil, com phaselistener tem como eu fazer validação só em algumas paginas? vlw t+

bom, só pra constar, nao sei se isso tem algum efeito mesmo, mas passou a funcionar hj depois q mudei, lembrei q quando estava mechendo com o file upload do primefaces, vi num forum que o filter dele no web.xml tinha que estar declarado antes de tudo, e hj eu mudei a declaração do filter da validação de usuario, colocando-a antes de tudo, e o método doFilter(…) passou a ser executado, mas agora o problema é q nenhuma pagina é exibida, vou colocar abaixo os trechos de código relevantes…

web.xml

<filter> <filter-name>areaRestrita</filter-name> <filter-class>controle.FiltrarRestricoes</filter-class> </filter> <filter-mapping> <filter-name>areaRestrita</filter-name> <url-pattern>*.xhtml</url-pattern> </filter-mapping>MBUsuarioLogado.java método que valida usuario e joga na session[code]public void login() {
boolean nomeOk = false;
boolean senhaOk = false;

    usuarioLogado = null;
    usuarios.clear();
    
    Criteria c = hu.getCriteria(Usuarios.class);
    usuarios = dao.listarCriteria(c);
    
    for (Usuarios u : usuarios) {
        if (u.getNome().equals(nome)) {
            nomeOk = true;
            if (u.getSenha().equals(senha)) {
                senhaOk = true;
                usuarioLogado = u;
            }
            break;
        }
    }
    
    HttpSession ses = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
    ses.setAttribute("usuarioLogado", null);
    if (!nomeOk) { 
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Falhou", "Nome incorreto !")); 
    }
    if (!senhaOk) { 
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Falhou", "Senha incorreta !")); 
    }
    if (nomeOk && senhaOk) {
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Login OK", usuarioLogado.getNome()));
        ses.setAttribute("usuarioLogado", usuarioLogado);
        System.out.println("logou usuario " + usuarioLogado.getNome());
    }
    
    nome = "";
    senha = "";
}[/code]FiltrarRestricoes.java medodo doFilter(...)[code]public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    //Obtem a session
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    HttpSession session = req.getSession();
    String paginaRequisitada = req.getRequestURL().toString();
    
    //Usuarios usuario = (Usuarios) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("usuarioLogado");
    Usuarios usuario = null;
    
    if (session.getAttribute("usuarioLogado") != null) {
        usuario = (Usuarios) session.getAttribute("usuarioLogado");
        System.out.println("pegou o usuario " + usuario.getNome());
    }
    //se não há o atributo usuarioLogado e a pagina requisitada não é login.xhtml, redireciona para login.xthml
    if (usuario == null && !paginaRequisitada.contains("login.xhtml")) {
        System.out.println("redirecionou para pagina login");
        resp.sendRedirect("login.xhtml");
    } else {
        System.out.println("redirecionou para pagina " + paginaRequisitada);
        chain.doFilter(request, response);
    }
}[/code]eu ainda não intendi o pq, mas esses 2 System.out dizendo que redirecionou são impressos na tela "redirecionou para pagina login" e "redirecionou para pagina http://localhost:8080/SuperB/login.xhtml", mas no browser fica em branco, não aparece pagina nenhuma, só a URL que aparece.

Alguem tem idéia ?

EDITADO, falhou a net aqui, achei q nao tinha enviado e acabei enviando duas vezes a mensagem…

Mais simples que o JAAS ta difícil! :stuck_out_tongue:
Só indicar a tabela de usuarios e a de roles!

Configuração no Tomcat, através do server.xml, aqui:
http://tomcat.apache.org/tomcat-5.5-doc/realm-howto.html#JDBCRealm

Pessoal, pq quando eu vou da pagina index.xhtml pra pagina enviarPromocoesCliente.xhtml na url do browser fica aparencendo http://localhost:8080/SuperB/faces/index.xhtml ao invés de aparecer http://localhost:8080/SuperB/faces/enviarPromocoesCliente.xhtml, o filtro acaba não funcionando por causa disso !!! ele nunca acha a minha pagina restrita, mas sim index.xhtml ou se eu acrescentar o arquivo de estilos, ele acha estilos.css ao invés do nome da minha pagina restrita, abaixo tem o código do command link<h:commandLink action="./enviarPromocoesCliente.xhtml"> <h:outputText value="Admin" /> </h:commandLink>e o arquivo de estilos dentro da tag head<link href="./estilos/estilos.css" rel="stylesheet" type="text/css" />

tentei agora usando phaselistener[code]public class AuthorizationListener implements PhaseListener {

@Override
public void afterPhase(PhaseEvent event) {

    FacesContext facesContext = event.getFacesContext();
    String currentPage = facesContext.getViewRoot().getViewId();
   
    boolean isEnviarPromocoesCliente = false;
    if (currentPage != null) {
        if (currentPage.contains("enviarPromocoesCliente.xhtml")) {
            isEnviarPromocoesCliente = true;
        }
    }
    HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
    Usuarios currentUser = (Usuarios) session.getAttribute("usuarioLogado");

    System.out.println((isEnviarPromocoesCliente ? "é epc" : ("não é epc" + (currentPage != null ? " é " + currentPage : ""))) 
            + " | usuario: " + (currentUser == null ? "null" : currentUser.getNome()));
    
    if (isEnviarPromocoesCliente && currentUser == null) {
        System.out.println("entrou");
        NavigationHandler nh = facesContext.getApplication().getNavigationHandler();
        nh.handleNavigation(facesContext, null, "loginPage");
    }
}

@Override
public void beforePhase(PhaseEvent event) {
}

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

}[/code]e o facesconfig.xml[code]<?xml version='1.0' encoding='UTF-8'?>

<lifecycle>
    <phase-listener>controle.AuthorizationListener</phase-listener>
</lifecycle>

<navigation-rule>
    <from-view-id>/*</from-view-id>
    <navigation-case>
        <from-outcome>loginPage</from-outcome>
        <to-view-id>/index.xhtml</to-view-id>
    </navigation-case>
    <redirect/>
</navigation-rule>

[/code]mas não funcionou pelo problema descrito acima, o atraso na atualização da url, caramba nunca vi algo tão simples ser tão complicado, ou eu to sempre indo pelo lugar errado… acho q vou tentar agora com o JAAS, mas o que exatamente eu vou salvar nesse banco de dados, no campo user eu salvo um nome de usuario, mas o que exatamente eu salvo no campo role ?

pessoal, é isso então ? nao vai funcionar dessa forma pq o JSF trabalha sobre POST e tem atraso na atualização da URL, posso desistir ? eu vi sobre o uso da tag no faces-config.xml nas regras de navegação, mas segundo este tutorial http://www.rponte.com.br/tag/faces-configxml/não é certo fazer uso desta tag sem necessidade…

pessoal, segundo o tutorial aqui do guj sobre JAAS[quote]este modulo de autenticação será executado pelo servidor de aplicação, antes mesmo de acessar a aplicação[/quote]e não é isso q eu quero, eu quero validar usuario somente em determinadas paginas do site, então, voltei agora questão das URLs atrasadas, será q não tem a solução pra essas urls atrasadas? alguma idéia pra me ajudar ?