默认情况下,浏览器的后退按钮根本不会向服务器发送 HTTP 请求。相反,它从浏览器缓存中检索页面。这本质上是无害的,但确实让最终用户感到困惑,因为他/她错误地认为它确实来自服务器。
您所需要做的就是指示浏览器不要缓存受限制的页面。您可以使用一个简单的 servlet 过滤器来完成此操作,该过滤器设置适当的响应标头 https://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached-across-all-browsers:
@WebFilter
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 资源请求,其缓存实际上需要单独配置 https://stackoverflow.com/questions/15057932/jsf-cache-static-resources-filter)
要让它在每个 JSF 请求上运行,请在过滤器类上设置以下注释,假设<servlet-name>
of the FacesServlet
在你的网络应用程序中web.xml
is facesServlet
:
@WebFilter(servletNames={"facesServlet"})
或者,让它仅在特定的 URL 模式上运行,例如与受限页面匹配的 URL 模式,例如/app/*
, /private/*
, /secured/*
,或者这样,在过滤器类上设置以下注释:
@WebFilter("/app/*")
如果您已经有一个过滤器,您甚至可以在检查登录用户的过滤器中执行相同的工作。
如果您碰巧使用 JSF 实用程序库OmniFaces http://omnifaces.org,那么你也可以抓住它CacheControlFilter http://showcase.omnifaces.org/filters/CacheControlFilter。这显然也考虑了 JSF 资源。
也可以看看:
- 防止用户在注销后看到以前访问过的安全页面 https://stackoverflow.com/questions/4194207/prevent-user-from-going-back-to-the-previous-secured-page-after-logout
- 会话过期时的授权重定向不适用于提交 JSF 表单,页面保持不变 https://stackoverflow.com/questions/14580267/authorization-redirect-on-session-expiration-does-not-work-on-submitting-a-jsf-f/
- JSF 2.0 View Scope 后退按钮安全吗? https://stackoverflow.com/questions/9930900/is-jsf-2-0-view-scope-back-button-safe/