Invalidating session with CDI+JSF not working

2019-06-25 06:25发布

问题:

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;
}

回答1:

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:

  • How to invalidate session in JSF 2.0?
  • Performing user authentication in Java EE / JSF using j_security_check


回答2:

Use this piece of code inside logout method:

HttpSession oldsession = (HttpSession) FacesContext
                .getCurrentInstance().getExternalContext().getSession(false);
oldsession.invalidate();

This will work. Let me know please if it was helpful for you.