1

这是我的注销方法:

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";
}

调用此方法后,浏览器历史记录中的导航仍然有效。我该如何解决这个问题?

4

1 回答 1

6

当您设置响应标头时,它仅适用于当前响应,而不适用于所有先前的响应(受限页面)或未来的响应(redirect(!) 及之后的响应)。您实际上想要关闭对受限请求的所有响应的浏览器缓存。事实上,正如您在评论中猜到的那样,您应该为此使用servlet 过滤器

另一个问题是,当您调用 时response.setHeader(),您基本上会覆盖任何先前设置的标头。您不想这样做,如果并且不存在,must-revalidate则完全没有效果。您需要将逗号分隔的值设置为单个标题,或使用.no-cacheno-storeresponse.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相应地更改 URL 模式。

完成后,您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";
}
于 2012-09-22T09:37:39.287 回答