PhaseListener dúvidas e problemas

Bom dia galera!

Estava precisando fazer uma validação de login na minha página onde uso JSF 1.2, RichFaces 3.2.1 e Facelets tudo feito no NetBeans.
Pesquisando encontrei um bom material e recomendação de que eu criasse um PhaseListener para isso.
Pois bem, foi o que fiz…

Mas num certo ponto ta dando null pointer exception, ta marcado no código:

public class SecurityListener implements PhaseListener {

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

     public void beforePhase(PhaseEvent event) {
        FacesContext facesContext = event.getFacesContext();
        //nessa linha debaixo ta dando o NULL pointer quando chamo o getViewRoot ele me retorna nulo...
        String currentPage = facesContext.getViewRoot().getViewId();

        boolean isLoginPage = (currentPage.lastIndexOf("loginGUI.jsf") > -1);

        HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);

        //recupero meu managed bean de sessao com os dados do usuario
        UsuarioBean currentUser = (UsuarioBean) session.getAttribute("UsuarioBean");

        //valida, se não for a pagina de login E o usuario não estiver logado, manda ele de volta pro login...
        if (!isLoginPage && !currentUser.isIsLogado()) {
            NavigationHandler nh = facesContext.getApplication().getNavigationHandler();
            nh.handleNavigation(facesContext, null, "gotoLogin");
        }
    }

    public void afterPhase(PhaseEvent event) {
    }
}

Resumindo, por causa desse NULLPointerException não consigo verificar se o usuário ta indo pra página de login, ai ele nem passa pelo método do bean de login, volta sempre pra página de login.

Por enquanot é só, se alguém tiver alguma dica de PhaseListeners eu agradeceria muito uma ajuda.

Grato!!

edit: troquei quote por code

Tenho um tutorial ótimo sobre PhaseListeners aqui : http://balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html

O unico problema do seu codigo é que você está implementando no evento errado, o NullPointerException está ocorrendo pq no beforePhase, o viewRoot ainda não foi recuperado, o método que você tem q implementar é o afeterPhase.

Abraço

Certo, é verdade!

Mas tem um problema, ele não está chamando o método do meu ManagedBean pra logar e nem ta considerando as menssagens que o <f:validate/> de alguns campos podem voltar.
Tem algum modo de contornar isso?!

Abraços!

Acho que funcionou, ficou assim:

public void afterPhase(PhaseEvent event) {
        System.out.println("<-----------------VALIDANDO REQUISIÇÃO------------------>");
        FacesContext facesContext = event.getFacesContext();

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

        boolean isLoginPage = (currentPage.lastIndexOf("loginGUI.xhtml") > -1);
        HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);

        UsuarioBean currentUser = (UsuarioBean) session.getAttribute("UsuarioBean");

        if (!isLoginPage && !currentUser.isIsLogado()) {
            System.out.println("<-----------------USUÁRIO NÃO LOGADO------------------>");
            NavigationHandler nh = facesContext.getApplication().getNavigationHandler();
            nh.handleNavigation(facesContext, null, "gotoLogin");
        }
    }

Ele não tava entendendo quando era a página de login e não chamava o método do bean, ai mudei a extensão de “.jsf” pra “.xhtml” e parece que ta funcionando.
Mais testes serão feitos.

Muito obrigado pela ajuda!! Abraços!

Olá amigo, td bem??

Estou tentando fazer a mesma implementação que vc, mas eu vi que no seu código vc usa na linha 20:

if (!isLoginPage && !currentUser.isIsLogado()) { 

No meu caso, eu usei:

if (!isLoginPage && currentUser == null) { 

mas não deu certo… ele fica sempre voltando a pagina de login.
Me diz uma coisa: quem é o isIsLogado() onde vc criou esse método? e eu tb nao consegui colocar o ! no currentUser. ele nao aceita.

valeu man.

currentUser é um objeto de UsuarioBean que eu criei e joguei na sessão quando o usuário se loga.
isIsLogado é um método de UsuarioBean que retorna um booleano indicando se meu usuário que está na sessão está logado ou não no sistema.

e no beforePhase, vc está incluindo alguma regra??

Nadinha.

E ai, conseguiu?

Tipo assim: atá funciona, mas eu uso paginas em jsp, que tem abas dentro delas que chamam outras jsp’s. aí o que acontece: ele filtra, tudo direitinho, mas só abre 1 jsp. as outras, ele volta para a pagina de login…

o q tu acha q pode ser?

Posta seu PhaseListener e o método que roda quando o usuário loga que dou uma olhada.

ok, olha o meu código:

[code]package br.com.caelum.fj26.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;

public class AuthorizationListener implements PhaseListener {

/**
 * 
 */
private static final long serialVersionUID = 1L;

public void afterPhase(PhaseEvent event) {
	System.out.println("<-----------VALIDANDO REQUISIÇÃO------------>");

	FacesContext facesContext = event.getFacesContext();
	String currentPage = facesContext.getViewRoot().getViewId();

	boolean isLoginPage = (currentPage.lastIndexOf("olajsf.xhtml") > -1);
	HttpSession session = (HttpSession) facesContext.getExternalContext()
			.getSession(true);
	Object currentUser = (Object) session.getAttribute("currentUser");

	if (!isLoginPage && currentUser == null) {
		System.out.println("<-------usuario nao logado-------->");
		NavigationHandler nh = facesContext.getApplication()
				.getNavigationHandler();
		nh.handleNavigation(facesContext, null, "loginPage");
	}

}

public void beforePhase(PhaseEvent event) {

}

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

}
[/code]

Ok, mas está faltando uma parte, não?
Quando o usuário loga no sistema você tem que jogar esse usuario na sessão, correto?
Onde você faz isso?
Posta aqui preu ver pra vc.

Olha aqui:

LoginHandler

[code]package br.com.caelum.fj26;

import java.util.List;

import org.hibernate.Session;

import br.com.caelum.fj26.dao.Dao;
import br.com.caelum.fj26.dao.LoginDAO;
import br.com.caelum.fj26.modelo.Login;
import br.com.caelum.fj26.modelo.Usuario;
import br.com.caelum.fj26.util.HibernateUtil;

public class LoginHandler {

private LoginDAO loginDAO = new LoginDAO();

/** Creates a new instance of ControleLogin */
public LoginHandler() {

}

private Login LO = new Login();

// 
public Login getLO() {
	return LO;
}

public void setLO(Login LO) {
	this.LO = LO;
}

public String login() {
	System.out.println("usuario= " + LO.getUsuario());
	System.out.println("password= " + LO.getPassword());

	boolean ok = loginDAO.Login(LO.getUsuario(), LO.getPassword(), "1");
	if (ok == true) {
		System.out.println("USUARIO LOGADO COM SUCESSO");
		return "ok";

	}
	boolean admin = loginDAO.Login(LO.getUsuario(), LO.getPassword(), "2");
	if (admin == true) {
		System.out.println("ADMIN LOGADO COM SUCESSO");
		return "admin";
	} else
		System.out.println("USUARIO/SENHA INVALIDO");
	return "erro";
}

public List<Usuario> getUsuarios() {
	System.out.println("carregando usuarios ...");
	Session session = HibernateUtil.currentSession();
	Dao<Usuario> dao = new Dao<Usuario>(session, Usuario.class);
	return dao.list();
}

}[/code]

Além disso, eu utilizo uma classe HibernateUtil e uma HibernateSessionFilter: Olha abaixo:

[code]package br.com.caelum.fj26.util;

import org.apache.log4j.Logger;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.AnnotationConfiguration;

//import org.postgresql.core.Logger;

public class HibernateUtil {

private static Logger logger = Logger.getLogger(HibernateUtil.class);



private static SessionFactory sessionFactory;



// ajuda a guardar as coisas na thread

private static ThreadLocal<Session> sessions = new ThreadLocal<Session>();



static {

	sessionFactory = new AnnotationConfiguration().configure()

			.buildSessionFactory();

}



public static Session openSession() {

	if (sessions.get() != null) {

		logger.error("Alguem nao fechou uma j&#65533; aberta!!");

		// grave, alguem nao fechou uma j&#65533; aberta!

	}

	sessions.set(sessionFactory.openSession());

	return sessions.get();

}



public static void closeCurrentSession() {

	sessions.get().close();

	sessions.set(null);

}



public static Session currentSession() {

	return sessions.get();

}

}
[/code]

[code]package br.com.caelum.fj26.util;

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

public class HibernateSessionFilter implements Filter {

public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc)

		throws IOException, ServletException {



	HibernateUtil.openSession();

	try {

		HibernateUtil.currentSession().beginTransaction();

		fc.doFilter(req, res);

		HibernateUtil.currentSession().getTransaction().commit();

	} catch (Exception e) {

		throw new ServletException(e);

	} finally {

		HibernateUtil.closeCurrentSession();

	}

}



public void init(FilterConfig c) {

}



public void destroy() {

}

}
[/code]

eae, o q vc achou?

Esperimente dessa forma:

PhaseListener:

 package br.com.caelum.fj26.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;  
   
 public class AuthorizationListener implements PhaseListener {  
   
     /** 
      *  
      */  
     private static final long serialVersionUID = 1L;  
   
     public void afterPhase(PhaseEvent event) {  
         System.out.println("<-----------VALIDANDO REQUISIÇÃO------------>");  
   
         FacesContext facesContext = event.getFacesContext();  
         String currentPage = facesContext.getViewRoot().getViewId();  
   
         boolean isLoginPage = (currentPage.lastIndexOf("olajsf.xhtml") > -1);  
         HttpSession session = (HttpSession) facesContext.getExternalContext()  
                 .getSession(true);  
         Boolean currentUser = (Boolean) session.getAttribute("currentUser");  
   
         if (!isLoginPage && currentUser == null) {  
             System.out.println("<-------usuario nao logado-------->");  
             NavigationHandler nh = facesContext.getApplication()  
                     .getNavigationHandler();  
             nh.handleNavigation(facesContext, null, "loginPage");  
         } else{ //isso aqui ta mto porco, mude a logica por favor
             if(currentUser != null && !currentUser){
                  System.out.println("<-------usuario nao logado-------->");  
             NavigationHandler nh = facesContext.getApplication()  
                     .getNavigationHandler();  
             nh.handleNavigation(facesContext, null, "loginPage");   
             }
         }
     }  
   
     public void beforePhase(PhaseEvent event) {  
   
     }  
   
     public PhaseId getPhaseId() {  
         return PhaseId.RESTORE_VIEW;  
     }  
   
 } 

LoginHandler:

 package br.com.caelum.fj26;  

    import java.util.List;  
      
    import org.hibernate.Session;  
      
    import br.com.caelum.fj26.dao.Dao;  
    import br.com.caelum.fj26.dao.LoginDAO;  
    import br.com.caelum.fj26.modelo.Login;  
   import br.com.caelum.fj26.modelo.Usuario;  
   import br.com.caelum.fj26.util.HibernateUtil;  
     
   public class LoginHandler {  
     
       private LoginDAO loginDAO = new LoginDAO();  
     
       /** Creates a new instance of ControleLogin */  
       public LoginHandler() {  
     
       }  
     
       private Login LO = new Login();  
     
       //   
       public Login getLO() {  
           return LO;  
       }  
     
       public void setLO(Login LO) {  
           this.LO = LO;  
       }  
     
       public String login() {  
           System.out.println("usuario= " + LO.getUsuario());  
           System.out.println("password= " + LO.getPassword());  

           HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
     
           boolean ok = loginDAO.Login(LO.getUsuario(), LO.getPassword(), "1");  
           if (ok == true) {  
               System.out.println("USUARIO LOGADO COM SUCESSO");  
               return "ok";  
     
           }  
           //poe booleano na sessao
           session.setAttribute("UsuarioBean",ok);           

           //pra que isso aqui embaixo?
           boolean admin = loginDAO.Login(LO.getUsuario(), LO.getPassword(), "2");  
           if (admin == true) {  
               System.out.println("ADMIN LOGADO COM SUCESSO");  
               return "admin";  
           } else  
               System.out.println("USUARIO/SENHA INVALIDO");  
           return "erro";  
       }  
     
       public List<Usuario> getUsuarios() {  
           System.out.println("carregando usuarios ...");  
           Session session = HibernateUtil.currentSession();  
           Dao<Usuario> dao = new Dao<Usuario>(session, Usuario.class);  
           return dao.list();  
       }  
     
   }  

pelo que eu entendi, vc está dando as mesmas condiçoes no if/else:

if (!isLoginPage && currentUser == null) { System.out.println("<-------usuario nao logado-------->"); NavigationHandler nh = facesContext.getApplication() .getNavigationHandler(); nh.handleNavigation(facesContext, null, "loginPage"); } else{ //isso aqui ta mto porco, mude a logica por favor if(currentUser != null && !currentUser){ System.out.println("<-------usuario nao logado-------->"); NavigationHandler nh = facesContext.getApplication() .getNavigationHandler(); nh.handleNavigation(facesContext, null, "loginPage"); }

eu entendi, que a na primeira parte:

if (!isLoginPage && currentUser == null) { System.out.println("<-------usuario nao logado-------->"); NavigationHandler nh = facesContext.getApplication() .getNavigationHandler();

aqui o código está verificando se o LoginPage e o currentUser nao sao nulos, caso nao sejam, ele dá um getAplication, getNavigationHandler.

caso contrário, ele carrega a segunda parte, como se fosse um if…, mandando para a pagina de login:

             nh.handleNavigation(facesContext, null, "loginPage");   

agora, me diz uma coisa: eu tenho q usar aqui uma pagina jsp ou xhtml??

boolean isLoginPage = (currentPage.lastIndexOf("olajsf.xhtml") > -1);

o comportamento muda de uma pra outra; se eu colocar olajsf.jsp, ele filtra legal, nao permite o acesso via url, eu logo com usuario, mas só acesso uma única jsp, naum consigo fazer inclusao de dados no banco nem abrir outra jsp. Se eu colocar olajsf.xhtml, ele simplesmente nao loga, e volta a tela de login.

??? eita negocinho q está dando dor de cabeça… ehehe
valeu man pela força!!

eae, o que achou??

Olá Tchello, desculpa a demora.
Eu olhei a sua sugestão, mas estou com dúvida em dois pontos:
1o.: no LoginHandler, vc sugeriu isso:

HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);

Como eu devo proceder para implementar o facesContext, pois ele grifa de vermelho e não me sugere nenhuma importação nem implementação.

2o.: ainda no LoginHandler:

session.setAttribute("UsuarioBean",ok);

Onde eu irei utilizar esse atributo UsuarioBean?? no Phaselistener?? nao deveria ser “currentUser”?

Obrigado pela atenção.