Search code examples
sessionjsfcdiinvalidationphaselistener

Invalidating session with CDI+JSF not working


I'm trying to implement a logout in my application, so I made this:

public String logout(){
    try{
        FacesContext facesContext = FacesContext.getCurrentInstance();  
        ExternalContext ex = facesContext .getExternalContext();  
        ex.invalidateSession(); 
        return "success"; 
    }catch(Exception e){
        return "error";
    }
}

But when I check if the user is logged, it says yes:

public class AuthenticateListener implements PhaseListener {


    @Override
    public void afterPhase(PhaseEvent event) {
        AuthorizedUser authorized = (AuthorizedUser) Util.getHandler("authorized");
        if (authorized.getUser() == null) {
            System.out.println("Not Logged");
        } else {
            System.out.println("Logged");
        }
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        // TODO Auto-generated method stub

    }

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

}

Am I missing something? Shouldn't I get a new instance of AuthorizedUser (sessionScoped) after invalidating my session?

EDIT: Adding the getHandler, if someone needs it ;)

public static Object getHandler(String handlerName) {

    FacesContext facesContext = FacesContext.getCurrentInstance();
    ELContext elContext = facesContext.getELContext();
    ELResolver resolver = facesContext.getApplication().getELResolver();

    Object uh = resolver.getValue(elContext, null, handlerName);
    return uh;
}

Solution

  • The session is still available in the current request-response. It's not available anymore in the next request. You need to send a redirect after the invalidate so that the browser will be instructed to send a new request on the given URL.

    return "success?faces-redirect=true"; 
    

    Or if you're still using old fashioned navigation cases (the return values namely suggests that; it's strange to have a view with filename "success"), then add <redirect/> to the navigation case instead.

    If that still doesn't work, then the bug is in how you're storing the user in session. For example, it's instead actually been stored in the application scope which may happen when you mix CDI @Named with JSF @SessionScoped, or when you assigned the logged-in user as a static variable instead of an instance variable.

    See also: