这是我的退出方法:
public String logout() throws IOException, ServletException
{
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext ec = context.getExternalContext();
HttpSession session = (HttpSession) ec.getSession(false);
HttpServletResponse response = (HttpServletResponse) ec.getResponse();
final HttpServletRequest request = (HttpServletRequest)ec.getRequest();
session.invalidate();
Cookie[] cookies = request.getCookies();
Cookie opentoken = null;
for(Cookie c : cookies){
if (c.getName().equals("opentoken")){
if (session != null){
opentoken = c;
opentoken.setMaxAge(0);
opentoken.setValue("");
response.addCookie(opentoken);
response.sendRedirect(request.getContextPath());
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Cache-Control", "no-store");
response.setHeader("Cache-Control", "must-revalidate");
response.setHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT");//past date
}
break;
}
}
context.getExternalContext().getSessionMap().remove("#{LogoutBean}");
return "login.xhtml?faces-redirect=false";
}
调用此方法后,浏览器历史记录中的导航仍然有效。我怎么解决这个问题?
答案 0 :(得分:6)
设置响应标头时,它仅应用于当前响应,而不应用于所有先前的响应(受限制的页面)或将来的响应(重定向(!)及其后)。实际上,您希望关闭受限请求的所有响应中的浏览器缓存。事实上,正如您在评论中所猜测的那样,您应该使用servlet filter。
另一个问题是,当您致电response.setHeader()
时,您基本上覆盖任何以前设置的标头。您不希望这样做,如果must-revalidate
和no-cache
不存在,则no-store
完全没有效果。您需要将值commaseparated设置为单个标头,或使用response.addHeader()
。
总而言之,您应该在webapp中拥有这样的课程:
@WebFilter("/app/*")
public class NoCacheFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
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);
}
// ... (just implement init() and destroy() with empty bodies).
}
此示例假定所有受限制的页面都在/app/*
URL模式后面可用。如果你的不同,例如/secured/*
,/user/*
,/admin/*
等,然后您需要相应地更改@WebFilter
中的网址格式。
完成后,您的logout()
可以简化如下:
public String logout() {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.invalidateSession();
if (ec.getRequestCookieMap().get("opentoken") != null) {
ec.addResponseCookie("opentoken", null, Collections.<String, Object>singletonMap("maxAge", 0));
}
return "login.xhtml?faces-redirect=true";
}