避免JSF Web应用程序上的后退按钮

Ton*_*ony 46 browser jsf back-button

我正在展示非常敏感的数据.用户从我的服务器注销后,我不希望其他用户能够看到数据点击浏览器的"后退"按钮.

我怎样才能做到这一点?

Bal*_*usC 79

默认情况下,浏览器的后退按钮根本不向服务器发送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);
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

(请注意,此过滤器会跳过JSF资源请求,其实际上需要单独配置其缓存)

为了得到它在每个JSF请求运行,设置过滤器类以下标注,假设的价值<servlet-name>FacesServlet在你的webapp的web.xmlfacesServlet:

@WebFilter(servletNames={"facesServlet"})
Run Code Online (Sandbox Code Playgroud)

或者,要让它在一个特定的URL模式只运行,这样的一个匹配受限制的页面,例如/app/*,/private/*,/secured/*,左右,设置过滤器类以下注释:

@WebFilter("/app/*")
Run Code Online (Sandbox Code Playgroud)

您甚至可以在过滤器中执行相同的工作,该过滤器会检查已登录的用户(如果已有).

如果您碰巧使用JSF实用程序库OmniFaces,那么您也可以抓住它CacheControlFilter.这也透明地考虑了JSF资源.

也可以看看:


Ton*_*ony 10

我还找到了另一个好的解决方案

在faces-config.xml中添加

<lifecycle>
    <phase-listener id="nocache">client.security.CacheControlPhaseListener</phase-listener>
</lifecycle>
Run Code Online (Sandbox Code Playgroud)

并实现以下类:

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");
    }
} 
Run Code Online (Sandbox Code Playgroud)

  • 虽然这可能有用,但是使用JSF阶段监听器,而servlet过滤器也可以使用相同的功能,就像使用锤子而不是螺丝刀来解决问题一样. (8认同)

归档时间:

查看次数:

38181 次

最近记录:

9 年,8 月 前