我展示了非常敏感的数据。在用户从我的服务器注销后,我不希望另一个用户能够通过浏览器的“返回”按钮查看数据。
我该如何做到这一点?
我展示了非常敏感的数据。在用户从我的服务器注销后,我不希望另一个用户能够通过浏览器的“返回”按钮查看数据。
我该如何做到这一点?
默认情况下,浏览器的返回按钮根本不会向服务器发送HTTP请求。相反,它会从浏览器缓存中检索页面。这基本上是无害的,但确实会让最终用户感到困惑,因为他们错误地认为它真的来自服务器。
你所需要做的就是指示浏览器不要缓存受限页面。你可以使用一个简单的servlet过滤器来设置适当的响应头:
@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资源请求,其缓存实际上需要单独配置)
要使它在每个JSF请求上运行,请在过滤器类上设置以下注释,假设您的Web应用程序的web.xml
中FacesServlet
的<servlet-name>
值为facesServlet
:
@WebFilter(servletNames={"facesServlet"})
/app/*
,/private/*
,/secured/*
等,请在过滤器类上设置以下注释:@WebFilter("/app/*")
CacheControlFilter
。这也透明地考虑了JSF资源。我还发现了另一个好的解决方案。
在 faces-config.xml 中添加以下内容:
<lifecycle>
<phase-listener id="nocache">client.security.CacheControlPhaseListener</phase-listener>
</lifecycle>
并且实现以下类:
package client.security;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class CacheControlPhaseListener implements PhaseListener
{
public PhaseId getPhaseId()
{
return PhaseId.RENDER_RESPONSE;
}
public void afterPhase(PhaseEvent event)
{
}
public void beforePhase(PhaseEvent event)
{
FacesContext facesContext = event.getFacesContext();
HttpServletResponse response = (HttpServletResponse) facesContext
.getExternalContext().getResponse();
response.addHeader("Pragma", "no-cache");
response.addHeader("Cache-Control", "no-cache");
// Stronger according to blog comment below that references HTTP spec
response.addHeader("Cache-Control", "no-store");
response.addHeader("Cache-Control", "must-revalidate");
// some date in the past
response.addHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT");
}
}