How to redirect to the login page when the session expires?

こ雲淡風輕ζ 提交于 2020-01-01 03:46:33

问题


I have three JSF 2.0 web modules and I need to redirect to the login page when the session expires.

I have tried it using a HttpSessionListener, it is calling the sessionDestroyed() event method, but I am not able to forward/redirect the request in there. I think it is becasue there are no HttpServletRequest and HttpServletResponse objects.

I also tried it using a PhaseListener, but it results in a "too many redirects" error in the webbrowser.

public class SessionListener implements PhaseListener {

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

    public void beforePhase(PhaseEvent event) {
        if (!FacesContext.getCurrentInstance().isPostback()) {
            try {
                System.out.println("Session Destroyed");
                FacesContext.getCurrentInstance().getExternalContext().redirect("login.jsf");
            }
            catch (Exception e) {
                System.out.println("error" + e);
            }
        }
    }

    public void afterPhase(PhaseEvent event)  {
        try {
            System.out.println("Session Created");
        }
        catch (Exception e) {
            System.out.println("error" + e);
        }
    }

}

Why do those attempts not work and how can I solve it the best?


回答1:


It's not possible to send a redirect at exactly the moment when the session is expired. The client has namely not sent any HTTP request at that moment which you could then respond with a redirect.

You should just keep your existing authentication mechanism which redirects to the login page when the user is not logged-in anymore. You can at best improve it by adding a check if the user is been redirected to the login page because the session has been expired, or just because he has never logged in before (i.e. it's a fresh new request).

You can check for that by if HttpServletRequest#getRequestedSessionId() doesn't return null (which means that the client has sent a session cookie and thus assumes that the session is still valid) and HttpServletRequest#isRequestedSessionIdValid() returns false (which means that the session has been expired at the server side). You can do that in the very same filter where you're checking for the logged-in user (you do already have one, right? or are you using container managed authentication?).

User user = (User) session.getAttribute("user");

if (user == null) {
    String loginURL = request.getContextPath() + "/login.jsf";
    if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
        response.sendRedirect(loginURL + "?expired=true");
    } else {
        response.sendRedirect(loginURL);
    }
} else {
    chain.doFilter(request, response);
}

And then in the login.xhtml page check for it

<h:panelGroup rendered="#{param.expired}">
    <p>You have been redirected to the login page, because your session was expired.</p>
</h:panelGroup>

Your phase listener approach makes by the way no sense. It indeed sends a redirect on every single request causing it to run in an infinite loop. The restore view phase has absolutely nothing to do with the session expiration.




回答2:


Try to use

 FacesContext.getCurrentInstance().getApplication().getNavigationHandler().
       handleNavigation(context, null, "LoginForm");

But note that you should use Servlet Filter for these purposes, it's better to do not any redirection from PhaseListener because it's really error prone.



来源:https://stackoverflow.com/questions/10943016/how-to-redirect-to-the-login-page-when-the-session-expires

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!