2

我有三个 JSF 2.0 Web 模块,我需要在会话到期时重定向到登录页面。

我已经尝试使用它HttpSessionListener,它正在调用sessionDestroyed()事件方法,但我无法在其中转发/重定向请求。我认为这是因为没有HttpServletRequestHttpServletResponse对象。

我也尝试过使用 a PhaseListener,但它会导致网络浏览器中出现“重定向过多”错误。

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

}

为什么这些尝试不起作用,我怎样才能最好地解决它?

4

2 回答 2

5

无法在会话到期的那一刻发送重定向。客户端此时尚未发送任何 HTTP 请求,然后您可以使用重定向进行响应。

您应该只保留现有的身份验证机制,当用户不再登录时重定向到登录页面。您最多可以通过添加一个检查来改进它,如果用户被重定向到登录页面是因为会话已过期,或者只是因为他以前从未登录过(即这是一个全新的请求)。

您可以通过 if HttpServletRequest#getRequestedSessionId()doesn't return null(这意味着客户端已发送会话 cookie 并因此假定会话仍然有效)并HttpServletRequest#isRequestedSessionIdValid()返回false(这意味着会话已在服务器端过期)来检查这一点。您可以在检查登录用户的同一过滤器中执行此操作(您已经有一个,对吗?或者您是否使用容器管理的身份验证?)。

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

然后在login.xhtml页面中检查它

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

顺便说一句,您的相位监听器方法毫无意义。它确实在每个请求上发送重定向,导致它在无限循环中运行。恢复视图阶段与会话到期完全无关。

于 2012-06-08T14:25:10.560 回答
0

尝试使用

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

但请注意,您应该为这些目的使用 Servlet 过滤器,最好不要从 PhaseListener 进行任何重定向,因为它真的很容易出错。

于 2012-06-08T05:54:47.500 回答