http - 如何确保在所有浏览器都不缓存网页

  显示原文与译文双语对照的内容

调查表明,并非所有浏览器都以统一的方式尊重http缓存指令。

出于安全考虑,我们不希望在我们的应用程序的某个页面缓存,,由web浏览器。 这必须至少适用于以下浏览器:

  • IE 6 +
  • Firefox 1.5 +
  • Safari 3 +
  • Opera 9 +
  • yf_terminology_Chrome@#@#@#Chrome_yf_terminology

我们的需求来自一个安全测试。 从我们的网站注销后,你可以按back上一步button按钮并查看缓存的网页。

时间:

介绍

适用于所有提到的浏览器的正确的最小标头集:


Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0

Cache-Control/HTTP 1.1规范客户( Expires 旁边的一些浏览器隐式要求),的Pragma 是史前每个http 1.0规范客户和代理和 Expires 是每个http 1.1规范为客户和代理。 如果指定了上述三个 Cache-Control 参数,则其他参数无关紧要。 The Last-Modified header as included in most other answers here is only intersting if you later want to cache request, so you do not need to specify it at all.

如何设置它?

使用 PHP:


header('Cache-Control: no-cache, no-store, must-revalidate');//HTTP 1.1.
header('Pragma: no-cache');//HTTP 1.0.
header('Expires: 0');//Proxies.

使用 Java Servlet:


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.

使用 ASP.NET:


Response.AppendHeader("Cache-Control","no-cache, no-store, must-revalidate");//HTTP 1.1.
Response.AppendHeader("Pragma","no-cache");//HTTP 1.0.
Response.AppendHeader("Expires","0");//Proxies.

使用 ASP:


Response.addHeader"Cache-Control","no-cache, no-store, must-revalidate" ' HTTP 1.1.
Response.addHeader"Pragma","no-cache" ' HTTP 1.0.
Response.addHeader"Expires","0" ' Proxies.

使用 ruby 在 Rails:


response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate' # HTTP 1.1.
response.headers['Pragma'] = 'no-cache' # HTTP 1.0.
response.headers['Expires'] = '0' # Proxies.

使用 python 在 Flask:


resp.headers["Cache-Control"] ="no-cache, no-store, must-revalidate"
resp.headers["Pragma"] ="no-cache"
resp.headers["Expires"] ="0"

使用谷歌:


responseWriter.Header().Set("Cache-Control","no-cache, no-store, must-revalidate")//HTTP 1.1.
responseWriter.Header().Set("Pragma","no-cache")//HTTP 1.0.
responseWriter.Header().Set("Expires","0")//Proxies

使用 Apache .htaccess file:


<IfModule mod_headers.c>
 Header set Cache-Control"no-cache, no-store, must-revalidate"
 Header set Pragma"no-cache"
 Header set Expires 0
</IfModule>

使用 HTML:


<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>
<meta http-equiv="Pragma" content="no-cache"/>
<meta http-equiv="Expires" content="0"/>

HTML元标记 vs HTTP响应标头

必须知道的是,当一个html页面通过http连接,和一个标题出现在 http响应头和html <meta http-equiv> 标签,然后一个http响应头中指定会优先于htmlmeta标记。 只有通过 file:// URL从本地磁盘文件系统查看页面时,才会使用HTML元标记。 参见 W3 HTML规范第 5.2.2章。 当你没有以编程方式指定它们时,请小心,因为web服务器可以包含一些默认值。 通常,你最好只是不是指定htmlmeta标记,以避免混乱的初学者来说,和依赖http响应头。

正在验证实际的HTTP响应标头

要验证一个和另一个,你可以在 web browser工具集开发人员的HTTP流量监视器中看到/调试它们。 你可以在 Chrome/Firefox23+/IE9+, 中按 F12,然后打开"网络"或者"网络"选项卡面板,然后单击感兴趣的HTTP请求,以显示有关HTTP请求和响应的所有细节。 下面的来自 Chrome 截图:

Chrome developer toolset HTTP traffic monitor showing HTTP response headers on stackoverflow.com

我想在文件下载时设置这些头文件

首先,这个问题和答案是针对"网页"( HTML页面),而不是"文件下载"( PDF,zip,Excel等) 。 你最好将它们缓存起来,并在URI路径或者 QueryString 中使用一些文件版本标识符来强制重新下载已经更改的文件。 当在文件下载上应用这些no-cache头时,在使用HTTPS而不是HTTP来提供文件下载时,请注意 ie7/8 Bug 。 详细信息, IE 无法下载 foo.jsf. IE 无法打开这里网站。 请求的站点不可用或者找不到 。

(嘿,每个人:请不要没头没脑copy&粘贴所有标题你可以找到)

首先,你正试图实现根据http规范应该不可能,因为后退按钮历史不是一个缓存 :

历史机制和缓存是不同的。 特别是历史机制不应该试图显示一个资源当前状态的语义透明的视图。 相反,历史机制是为了显示用户时看到什么资源检索。

应该回到过去( 用户登录的时间到), 它并不期待之前打开网址导航。

然而,在实践中,由于"注销后返回"的恐慌,这是可能的。 它在非常特殊的情况下工作可靠:

  • 页面在 HTTPS 必须交付。 如果你不使用https,那么不打扰—不可靠,和页面已经 大的安全问题。
  • 你必须发送 Cache-Control: must-revalidate

你永远不需要:

  • 带缓存头的<meta>,但它根本不起作用。 完全无用。
  • post-check/pre-check —它是IE-only指令,只适用于可以缓存的资源。
  • 发送相同的标头两次或者多个部分。 一些最严重的php代码片段实际上取代以前的头,只有最后一个被发送。

如果你愿意,你可以添加:

  • no-store 如果你正在发送security-sensitive信息。
  • no-cache 或者 max-age=0,这将使资源( URL )"过时"And require browsers to check with server if there is a newer version ( must-revalidate already implies this even stronger )"。
  • Expires,过去的日期为 http/1.0 客户端( 尽管实际的http/1,0-only客户端可能不存在) 。

我发现这个页面上的所有答案仍然有问题。 特别是,我注意到当你通过点击back上一步button按钮访问IE8时,它们都不会停止使用缓存的版本。

经过大量的研究和测试,我发现我真正需要的两个头是:

Cache-Control: no-store
差异:*

有关不同标头的解释,请查阅 http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6

在 IE6-8,ff1.5-3 。5,Chrome 2 -3,4和 Opera 9 -10上,当单击指向页面的链接或者直接在地址栏中放置URL时,这些标头将从服务器请求。 ,覆盖了 99%所有浏览器使用的jan 10.

在IE6和 Opera 9 -10上,按下back上一步,按钮仍然导致缓存的版本被加载。 在我测试的所有其他浏览器上,他们从服务器获取了一个新的版本。 到目前为止,我还没有找到任何将导致那些浏览器在你按下back后退button按钮时不会返回缓存版本的页面的设置。

更新:写这个答案之后,我意识到我们的web服务器是识别本身作为http 1.0服务器。 我所列出的标题是正确的,以便从 HTTP 1.0服务器上的响应不被浏览器缓存。 对于一个http 1.1服务器,看看 balusc回答。

在进行了一些研究之后,我们想到了下面的标题列表,它们似乎涵盖了大多数浏览器:

在 ASP.NET 中,我们使用以下代码Fragment添加了这些内容:


Response.ClearHeaders(); 
Response.AppendHeader("Cache-Control","no-cache");//HTTP 1.1
Response.AppendHeader("Cache-Control","private");//HTTP 1.1
Response.AppendHeader("Cache-Control","no-store");//HTTP 1.1
Response.AppendHeader("Cache-Control","must-revalidate");//HTTP 1.1
Response.AppendHeader("Cache-Control","max-stale=0");//HTTP 1.1 
Response.AppendHeader("Cache-Control","post-check=0");//HTTP 1.1 
Response.AppendHeader("Cache-Control","pre-check=0");//HTTP 1.1 
Response.AppendHeader("Pragma","no-cache");//HTTP 1.0 
Response.AppendHeader("Expires","Mon, 26 Jul 1997 05:00:00 GMT");//HTTP 1.0

从:http://forums.asp.net/t/1013531.aspx 中找到

我发现 Web.Config 路由很有用( 试图将它添加到答案,但似乎没有被接受,所以在这里投递)


<configuration><system.webServer><httpProtocol><customHeaders>
 <add name="Cache-Control" value="no-cache, no-store, must-revalidate"/><!-- HTTP 1.1. -->
 <add name="Pragma" value="no-cache"/><!-- HTTP 1.0. -->
 <add name="Expires" value="0"/><!-- Proxies. -->
</customHeaders></httpProtocol></system.webServer></configuration>

下面是执行相同操作的express/node.js 方法:


app.use(function(req, res, next) {
 res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
 res.setHeader('Pragma', 'no-cache');
 res.setHeader('Expires', '0');
 next();
});

免责声明:我强烈建议阅读 @BalusC's 答案。 阅读以下缓存教程后: http://www.mnot.net/cache_docs/ ( 我建议你读读它),我相信它是正确的。 但是,由于历史原因,我将在下面包含我的原始答案:


我尝试了PHP的'接受'答案,但它对我不起作用。 然后我做了一些研究,发现了一个微小的变化,经过了测试,它工作了。 这就是:


header('Cache-Control: no-store, private, no-cache, must-revalidate');//HTTP/1.1
header('Cache-Control: pre-check=0, post-check=0, max-age=0, max-stale = 0', false);//HTTP/1.1
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');//Date in the past 
header('Expires: 0', false); 
header('Last-Modified: '.gmdate('D, d M Y H:i:s'). ' GMT');
header ('Pragma: no-cache');

可以这样做。问题是,当两次设置标题的相同部分时,如果 false 没有将作为第二个参数发送到头函数,头函数将简单地覆盖前面的header() 调用。 因此,当设置 Cache-Control 时,例如如果某人不想将所有参数放入一个 header() 函数调用中,他必须执行如下操作:


header('Cache-Control: this');
header('Cache-Control: and, this', false);

查看更完整的文档这里是

...