【问题标题】:Session management in JSF 2.0JSF 2.0 中的会话管理
【发布时间】:2013-07-22 01:08:21
【问题描述】:

我对如何在 JSF 2.0 中管理会话感到困惑。

我创建了 4 个页面,其中包含登录、数据、信息和 sessionexpires,一旦会话过期就会显示。

当我点击注销按钮时,它通过调用以下操作方法使会话无效:

public String logout(){
    FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
    return "logout?faces-redirect=true";
}

代码按预期将我重定向到注销页面,但是当我单击浏览器的后退按钮时,它会将我带到数据页面并显示所有信息,但我认为,如果会话已经过期,那么它应该显示 sessionexpires 页面。

如何实现所需的功能?

【问题讨论】:

  • 非常感谢@BalusC,但我的问题仍然不是点击后退按钮时完全缓存的页面,而是在缓存页面上,如果我使会话无效,为什么在点击命令按钮时会执行操作

标签: session jsf-2


【解决方案1】:

当用户单击浏览器的后退按钮时,您会看到以前的页面,这表明这些页面已被缓存并且是从浏览器的缓存中显示的,而不是从服务器请求的。要修复它,您需要适当地设置 HTTP 响应标头。这已在Making sure a web page is not cached, across all browsers 中预先回答。重复一下 BalusC,它们是:

response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.

设置这些标头的最合适的位置是 Web 过滤器,因为在那里您似乎不需要任何 JSF 物品。您可以在Avoid back button on JSF web application 的答案中找到更多信息。要重复 BalusC 的代码,您将拥有:

@WebFilter("/secured/*")
public class NoCacheFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

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

        chain.doFilter(req, res);
    }

    // ...

}

只是不要忘记告诉您需要过滤哪些页面。这样,请求的新页面将始终从服务器发送,并且不再被缓存。因此,如果用户在注销后尝试访问安全页面(通过会话失效和发送重定向),您的标准安全措施将启动(其他过滤器)阻止用户访问这些页面。

接下来要做的是解释JSF如何在会话无效/超时时处理已经打开的页面。换句话说,你怎么处理ViewExpiredExceptions。对于同步 POST 请求,How to handle session expiration and ViewExpiredException in JSF 2?javax.faces.application.ViewExpiredException: View could not be restored 以及 AJAX 请求的 Session timeout and ViewExpiredException handling on JSF/PrimeFaces ajax request 依次回答了这个问题。

基本上,对于前者,您需要将以下行添加到您的 web.xml:

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/expired.xhtml</location>
</error-page>

对于后者,我强烈建议您查看 JSF 实用程序库 OmniFaces 及其专为此目的设计的 FullAjaxExceptionHAndler

【讨论】:

  • 非常感谢@skuntsel,但我仍然想做的是,当人们点击缓存页面命令按钮时,它应该进入 sessionexpires 页面(因为我使会话无效),但不执行操作点击那个按钮
【解决方案2】:

即使在服务器上的会话无效后,浏览器也会将您带回数据页面,因为该页面已缓存在您的浏览器内存中。

关注this,了解浏览器后退按钮的工作原理。

您可以参考this 来解决您的问题。

【讨论】:

  • 感谢@joe,但这不是我的问题,我知道页面已缓存,正如我从 BalusC 从here 中学到的那样,但是如果我单击任何命令按钮,它会再次出现在背面页面上到 sessionexpire 页面,但不是通过该按钮请求页面。
猜你喜欢
  • 2011-08-01
  • 2011-06-12
  • 2011-12-05
  • 2018-11-16
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
  • 2012-12-11
  • 1970-01-01
相关资源
最近更新 更多