【问题标题】:How to move user to timeout page when session expires, if user click on browser back button如果用户单击浏览器后退按钮,如何在会话到期时将用户移动到超时页面
【发布时间】:2012-04-03 17:02:54
【问题描述】:

我正在使用 filter 处理 JSF 2.0 中的会话过期。这是代码

  @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
        throws IOException, ServletException {

    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;

    HttpSession session = httpServletRequest.getSession(false);

    if (session == null) {

        //session timeout check.
        if (httpServletRequest.getRequestedSessionId() != null && !httpServletRequest.isRequestedSessionIdValid()) {

            System.out.println("Session has expired");
            session = httpServletRequest.getSession(true);
            session.setAttribute("logedin", "0");    // public user               
            httpServletResponse.sendRedirect(timeoutPage);

        } else {

            session = httpServletRequest.getSession(true);
            session.setAttribute("logedin", "0");
            filterChain.doFilter(httpServletRequest, httpServletResponse);
        }
    } 
} //end of doFilter()

但问题是,当会话到期时,如果用户单击后退按钮,那么他会得到包含所有样式的页面。无论如何,当会话到期时,如果用户单击浏览器后退按钮,那么他会指向 timeoutPage。

还有一件事,我也在我的页面上使用 Prime Faces 组件,比如数据表。我正在使用分页。如果会话超时,并且我单击分页,则不会出现会话到期消息。似乎ajax请求不调用过滤器?如何连接我的 ajax 事件,或者您可以将数据表分页事件与会话到期联系起来?

谢谢

【问题讨论】:

    标签: jsf-2


    【解决方案1】:

    当会话到期时,如果用户点击后退按钮,那么他会得到所有样式的页面

    您需要告诉浏览器不要在浏览器缓存中缓存页面。浏览器应该向服务器发送完整的请求。

    filterChain.doFilter() 调用之前添加以下行。

    if (!httpServletRequest.getRequestURI().startsWith(httpServletRequest.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
        httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        httpServletResponse.setHeader("Pragma", "no-cache"); // HTTP 1.0.
        httpServletResponse.setDateHeader("Expires", 0); // Proxies.
    }
    

    如果会话超时,并且我单击分页,则不会出现会话到期消息。 ajax 请求好像没有调用过滤器?

    JSF ajax 请求需要带有 HTTP 状态 200 的 XML 响应。如果您发送同步重定向,则将发送 HTTP 状态 302 响应,JSF ajax 引擎将完全忽略该响应。相反,您应该发送带有特定 XML 的普通 HTTP 200 响应,该 XML 告诉 JSF ajax 引擎执行重定向。这样做而不是 httpServletResponse.sendRedirect() 然后:

    if ("partial/ajax".equals(httpServletRequest.getHeader("Faces-Request"))) {
        httpServletResponse.setContentType("text/xml");
        httpServletResponse.getWriter()
            .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
            .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", timeoutPage);
    }
    else {
        httpServletResponse.sendRedirect(timeoutPage);
    }
    

    请注意,当您已经在 J​​SF 上下文中时(例如,通过 PhaseListenerSystemEventListener 或者可能是 @ManagedBean),那么您可以只使用 ExternalContext#redirect() 方法。它将透明地相应地处理同步/异步请求。

    【讨论】:

    • HHmm 所以当我们设置..httpServletResponse.setHeader("Pragma", "no-cache");..这意味着现在如果我们按下浏览器返回按钮,那么我们的构造函数将被调用。如果我们不设置no-cache,那么当我们按下浏览器的返回按钮时,我们的构造函数就不会调用,而是浏览器使用它的缓存来显示页面。我说的对吗?
    • 如果 bean 是请求/视图范围的,那是正确的。浏览器改为向服务器发送一个完整的 HTTP 请求(您可以在过滤器中执行所有必要的检查),而不是显示浏览器缓存中的旧页面。
    • 还有一件事,因为您定义了 ajax 部分。您的意思是说,当我单击分页时,过滤器在会话到期时调用,但由于 HTTP 状态 302 响应而忽略了重定向请求。是吗?
    • 不,过滤器没有忽略重定向请求。 JSF ajax 引擎这样做是因为它只期望并支持状态为 200 的特定 XML 响应。默认情况下,即使是异常(状态 500)也会被忽略。另请参阅此相关问题stackoverflow.com/questions/9305144/…
    • 在一个设计合理的 JSF Web 应用程序中,动作方法都应该返回voidnull。页面到页面导航需要通过带有&lt;h:link&gt;&lt;h:outputLink&gt; 的GET 执行。另请参阅stackoverflow.com/questions/4317684/…
    猜你喜欢
    • 1970-01-01
    • 2012-09-17
    • 1970-01-01
    • 2012-06-20
    • 2013-07-09
    • 2014-03-21
    • 2020-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多