禁用浏览器前进/后退按钮的网页缓存

时间:2022-02-15 17:03:26

I am using following meta tags to prevent browser caching for page:

我使用以下元标记来阻止页面的浏览器缓存:

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="Vary" content="*" />

Case:

  1. Browser is already opened with page1.
  2. 已使用page1打开浏览器。

  3. New link is pasted in the browser address bar and now secured page page2 is opened.
  4. 新链接将粘贴到浏览器地址栏中,现在将打开安全页面第2页。

  5. User performs action on page2 and is redirected to page3.
  6. 用户在第2页上执行操作,并重定向到第3页。

When clicking back button on page3, then user gets redirected to page1 (no caching and works fine in this case). When user clicks forward button on page1, then the user is forwarded to the secured page page2. This shouldn't happen.

当单击第3页上的后退按钮时,用户将被重定向到page1(在这种情况下,没有缓存并且工作正常)。当用户单击第1页上的转发按钮时,用户将转发到安全页面2。这不应该发生。

All of above is tested on IE9.

以上所有都在IE9上进行了测试。

How is this caused and how can I solve it?

这是怎么造成的,如何解决?

2 个解决方案

#1


6  

Your initial attempt with HTML <meta http-equiv> tags specifies the right header values, however, this doesn't work at all because your pages are already served over HTTP. The <meta http-equiv> headers specifies "HTTP-equivalent" headers which are only used when the pages are not served using the HTTP protocol.

您使用HTML 标记的初始尝试指定了正确的标头值,但是,这根本不起作用,因为您的网页已经通过HTTP提供。 标头指定“HTTP等效”标头,仅在未使用HTTP协议提供页面时使用。

For example, when the pages are opened from local disk file system like as if you were doubleclicking a .html file in local disk file system explorer. This would open the .html file via file:// URI instead of http:// URI.

例如,从本地磁盘文件系统打开页面时就像在本地磁盘文件系统资源管理器中双击.html文件一样。这将通过file:// URI而不是http:// URI打开.html文件。

You should be setting those headers on the real HTTP response. You can investigate the headers of the current HTTP response by pressing F12 in Chrome/FireFox>=23/IE>=9 and exploring the HTTP traffic in Network tab. In case of specifically IE9/10, click the Start capturing button, reload the page, select the HTML page, click Go to detailed view button and finally click the Response headers tab. Here's a screenshot of how it look like in IE10 on your current question:

您应该在真实的HTTP响应上设置这些标头。您可以通过在Chrome / FireFox> = 23 / IE> = 9中按F12并在网络选项卡中浏览HTTP流量来调查当前HTTP响应的标头。如果是IE9 / 10,请单击“开始捕获”按钮,重新加载页面,选择HTML页面,单击“转到详细视图”按钮,最后单击“响应标头”选项卡。以下是您当前问题在IE10中的外观截图:

禁用浏览器前进/后退按钮的网页缓存

The right way to get those headers to end up there is using HttpServletResponse#setHeader() and friends like setDateHeader(), addHeader(), etc. As you figured, one way is a servlet filter.

使这些标题最终的正确方法是使用HttpServletResponse#setHeader()和朋友,如setDateHeader(),addHeader()等。如您所知,一种方法是servlet过滤器。

See also:

#2


1  

I found out that the best solution is the following filter:

我发现最好的解决方案是以下过滤器:

import java.io.IOException;
import javax.faces.application.ResourceHandler;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet Filter implementation class NoCacheFilter
 */
  @WebFilter(urlPatterns = {"*.xhtml"})
  public class NoCacheFilter implements Filter {

/**
 * Default constructor. 
 */
public NoCacheFilter() {
    // TODO Auto-generated constructor stub
}

/**
 * @see Filter#destroy()
 */
public void destroy() {
    // TODO Auto-generated method stub
}

/**
 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
 */

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    // apply no caching for all web pages except resources, you can customize that to be applied for specific pages
    if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
        res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
        res.setDateHeader("Expires", 0); // Proxies.
    }

    chain.doFilter(request, response);
}
/**
 * @see Filter#init(FilterConfig)
 */
public void init(FilterConfig fConfig) throws ServletException {
    // TODO Auto-generated method stub
}

}

according to the answer in this question:

根据这个问题的答案:

Redirect to login page when user clicks on back button after logout in JSF

用户在JSF注销后单击后退按钮时重定向到登录页面

#1


6  

Your initial attempt with HTML <meta http-equiv> tags specifies the right header values, however, this doesn't work at all because your pages are already served over HTTP. The <meta http-equiv> headers specifies "HTTP-equivalent" headers which are only used when the pages are not served using the HTTP protocol.

您使用HTML 标记的初始尝试指定了正确的标头值,但是,这根本不起作用,因为您的网页已经通过HTTP提供。 标头指定“HTTP等效”标头,仅在未使用HTTP协议提供页面时使用。

For example, when the pages are opened from local disk file system like as if you were doubleclicking a .html file in local disk file system explorer. This would open the .html file via file:// URI instead of http:// URI.

例如,从本地磁盘文件系统打开页面时就像在本地磁盘文件系统资源管理器中双击.html文件一样。这将通过file:// URI而不是http:// URI打开.html文件。

You should be setting those headers on the real HTTP response. You can investigate the headers of the current HTTP response by pressing F12 in Chrome/FireFox>=23/IE>=9 and exploring the HTTP traffic in Network tab. In case of specifically IE9/10, click the Start capturing button, reload the page, select the HTML page, click Go to detailed view button and finally click the Response headers tab. Here's a screenshot of how it look like in IE10 on your current question:

您应该在真实的HTTP响应上设置这些标头。您可以通过在Chrome / FireFox> = 23 / IE> = 9中按F12并在网络选项卡中浏览HTTP流量来调查当前HTTP响应的标头。如果是IE9 / 10,请单击“开始捕获”按钮,重新加载页面,选择HTML页面,单击“转到详细视图”按钮,最后单击“响应标头”选项卡。以下是您当前问题在IE10中的外观截图:

禁用浏览器前进/后退按钮的网页缓存

The right way to get those headers to end up there is using HttpServletResponse#setHeader() and friends like setDateHeader(), addHeader(), etc. As you figured, one way is a servlet filter.

使这些标题最终的正确方法是使用HttpServletResponse#setHeader()和朋友,如setDateHeader(),addHeader()等。如您所知,一种方法是servlet过滤器。

See also:

#2


1  

I found out that the best solution is the following filter:

我发现最好的解决方案是以下过滤器:

import java.io.IOException;
import javax.faces.application.ResourceHandler;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet Filter implementation class NoCacheFilter
 */
  @WebFilter(urlPatterns = {"*.xhtml"})
  public class NoCacheFilter implements Filter {

/**
 * Default constructor. 
 */
public NoCacheFilter() {
    // TODO Auto-generated constructor stub
}

/**
 * @see Filter#destroy()
 */
public void destroy() {
    // TODO Auto-generated method stub
}

/**
 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
 */

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    // apply no caching for all web pages except resources, you can customize that to be applied for specific pages
    if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
        res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
        res.setDateHeader("Expires", 0); // Proxies.
    }

    chain.doFilter(request, response);
}
/**
 * @see Filter#init(FilterConfig)
 */
public void init(FilterConfig fConfig) throws ServletException {
    // TODO Auto-generated method stub
}

}

according to the answer in this question:

根据这个问题的答案:

Redirect to login page when user clicks on back button after logout in JSF

用户在JSF注销后单击后退按钮时重定向到登录页面