如何在所有浏览器上控制网页caching?

我们的调查显示,并非所有浏览器都以统一的方式遵守http cache指示。

出于安全原因,我们不希望应用程序中的某些页面被Web浏览器caching。 这至less适用于以下浏览器:

  • Internet Explorer 6+
  • Firefox 1.5+
  • Safari 3+
  • 歌剧9+

我们的要求来自安全testing。 从我们的网站注销后,您可以按下后退button并查看caching的页面。

介绍

在所有提到的客户端(和代理服务器)中工作的正确的最小标题集合:

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.0和1.1规范。 在HTTP 1.1中, Cache-Control优先于Expires ,所以它毕竟只用于HTTP 1.0代理。

如果您不关心IE6及其在仅通过no-store提供通过HTTPS提供页面时的破坏caching,则可以省略Cache-Control: no-cache

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

如果你不关心IE6和HTTP 1.0客户端(HTTP 1.1是1997年推出的),那么你可以省略Pragma

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

如果你不关心HTTP 1.0代理,那么你可以省略Expires

 Cache-Control: no-store, must-revalidate 

另一方面,如果服务器自动包含一个有效的Date标题,那么理论上也可以省略Cache-Control ,只依赖Expires

 Date: Wed, 24 Aug 2016 18:32:02 GMT Expires: 0 

但是,如果最终用户操纵操作系统date并且客户端软件依赖它,则可能会失败。

如果指定了上述Cache-Control参数,则其他Cache-Control参数(如max-age是不相关的。 Last-Modified头部包含在大多数其他答案中, 只有在你真正想要caching请求时才有意思,所以你根本不需要指定它。

如何设置?

使用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或Node.js:

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

使用ASP.NET-MVC

 Response.Cache.SetCacheability(HttpCacheability.NoCache); // HTTP 1.1. Response.Cache.AppendCacheExtension("no-store, must-revalidate"); Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0. Response.AppendHeader("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 on Rails或Flask上的Python:

 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. 

使用Google Go:

 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文件:

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

使用HTML4:

 <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" /> 

使用Python /金字塔:

 def my_api_call(context, request): # disable caching request.response.headerlist.extend( ( ('Cache-Control', 'no-cache, no-store, must-revalidate'), ('Pragma', 'no-cache'), ('Expires', '0') ) ) 

HTML元标记与HTTP响应标题

重要的是要知道,当通过HTTP连接提供HTML页面,并且HTTP响应头部和HTML <meta http-equiv>标签中存在头部时,那么HTTP响应头部中指定的头部将优先通过HTML元标记。 只有当通过file:// URL从本地磁盘文件系统查看页面时才会使用HTML元标记。 另请参阅W3 HTML规范章节5.2.2 。 请不要以编程方式指定它们,因为Web服务器可以包含一些默认值。

通常,您最好不要指定HTML元标记以避免初学者混淆,并依赖硬HTTP响应头。 而且,特别是那些<meta http-equiv>标签在HTML5中是无效的。 只有HTML5规范中列出的http-equiv值是允许的。

validation实际的HTTP响应头

要validation这一个,你可以在web浏览器的开发者工具集的HTTPstream量监视器中看到/debugging它们。 您可以通过在Chrome / Firefox23 + / IE9 +中按F12,然后打开“networking”或“networking”选项卡面板,然后单击感兴趣的HTTP请求来发现有关HTTP请求和响应的所有细节。 以下屏幕截图来自Chrome:

Chrome开发人员工具集HTTP通信监视器,在stackoverflow.com上显示HTTP响应头

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

首先,这个问题和答案是针对“网页”(HTML页面),而不是“文件下载”(PDF,ZIP,Excel等)。 您最好将它们caching起来,并使用URIpath或查询string中的某个文件版本标识符来强制重新下载更改的文件。 当在文件下载中使用这些无caching标头时,请注意通过HTTPS而不是HTTP提供文件下载时的IE7 / 8错误。 有关详细信息,请参阅IE无法下载foo.jsf。 IE浏览器无法打开这个网站。 请求的网站不可用或无法find 。

(嘿,大家:请不要盲目地复制和粘贴所有标题,你可以find)

首先, 后退button的历史不是caching

新鲜度模型(4.2节)不一定适用于历史机制。 也就是说,历史机制即使已经过期也可以显示先前的表示。

在旧的HTTP规范中,措辞更加明显,明确地告诉浏览器忽略后退button历史logging的caching指令。

返回应该返回(到用户login的时间)。 它不会前进到以前打开的URL。

但实际上,在非常特殊的情况下,caching会影响后退button:

  • 页面必须通过HTTPS传递,否则这种caching破坏将不可靠。 另外,如果你不使用HTTPS,那么你的页面很容易被其他许多方面的login窃取。
  • 你必须发送Cache-Control: no-store, must-revalidate (一些浏览器观察no-store和一些观察must-revalidate

永远不需要任何:

  • 带caching头的<meta> – 根本不起作用。 完全没用。
  • post-check / pre-check – 这是仅适用于可caching资源的仅限IE的指令。
  • 发送相同的头两次或十几个部分。 一些PHP代码片段实际上取代了之前的头文件,导致只发送最后一个头文件。

如果你想,你可以添加:

  • no-cachemax-age=0 ,这将使资源(URL)“陈旧”,并要求浏览器检查服务器,如果有一个更新的版本( no-store已经暗示这更强大)。
  • HTTP / 1.0客户端过去的date会Expires (尽pipe现在真正的只有HTTP / 1.0的客户端是完全不存在的)。

奖金: 新的HTTPcachingRFC 。

正如所说的,你想要的不是停用caching,而是停用历史缓冲区。 不同的浏览器有自己的微妙的方法来禁用历史缓冲区。

在Chrome(v28.0.1500.95 m)中,我们只能通过Cache-Control: no-store来完成此操作。

在FireFox(v23.0.1)中,任何一个都可以工作:

  1. Cache-Control: no-store

  2. Cache-Control: no-cache (仅限https)

  3. Pragma: no-cache (仅限https)

  4. Vary: * (仅限https)

在Opera(v12.15)中,我们只能通过Cache-Control: must-revalidate来做到这一点Cache-Control: must-revalidate (仅限https)。

在Safari(v5.1.7,7534.57.2)中,其中任何一个都可以工作:

  1. Cache-Control: no-store
    <body onunload="">在html中

  2. Cache-Control: no-store (仅限https)

在IE8(v8.0.6001.18702IC)中的任何一个将工作:

  1. Cache-Control: must-revalidate, max-age=0

  2. Cache-Control: no-cache

  3. Cache-Control: no-store

  4. Cache-Control: must-revalidate
    Expires: 0

  5. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT

  6. Pragma: no-cache (仅限https)

  7. Vary: * (仅限https)

结合上述给我们这个解决scheme适用于Chrome 28,FireFox 23,IE8,Safari 5.1.7和Opera 12.15: Cache-Control: no-store, must-revalidate (仅限https)

请注意,因为Opera不会停用纯HTTP页面的历史缓冲区,所以需要https。 如果你真的无法获得HTTPS并且你准备忽略Opera,那么你可以做的最好的是:

 Cache-Control: no-store <body onunload=""> 

下面显示了我的testing的原始日志:

HTTP:

  1. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Opera 12.15
    成功:Chrome 28,FireFox 23,IE8,Safari 5.1.7

  2. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Opera 12.15
    成功:Chrome 28,FireFox 23,IE8,Safari 5.1.7

  3. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    失败:Safari 5.1.7,Opera 12.15
    成功:Chrome 28,FireFox 23,IE8

  4. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    失败:Safari 5.1.7,Opera 12.15
    成功:Chrome 28,FireFox 23,IE8

  5. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
    成功:IE8

  6. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
    成功:IE8

  7. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
    成功:IE8

  8. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
    成功:IE8

  9. Cache-Control: no-store
    失败:Safari 5.1.7,Opera 12.15
    成功:Chrome 28,FireFox 23,IE8

  10. Cache-Control: no-store
    <body onunload="">
    失败:Opera 12.15
    成功:Chrome 28,FireFox 23,IE8,Safari 5.1.7

  11. Cache-Control: no-cache
    失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
    成功:IE8

  12. Vary: *
    失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7,Opera 12.15
    成功:没有

  13. Pragma: no-cache
    失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7,Opera 12.15
    成功:没有

  14. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
    成功:IE8

  15. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
    成功:IE8

  16. Cache-Control: must-revalidate, max-age=0
    失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
    成功:IE8

  17. Cache-Control: must-revalidate
    Expires: 0
    失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
    成功:IE8

  18. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
    成功:IE8

  19. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7,Opera 12.15
    成功:没有

HTTPS:

  1. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7,Opera 12.15
    成功:没有

  2. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    <body onunload="">
    失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7,Opera 12.15
    成功:没有

  3. Vary: *
    失败:Chrome 28,Safari 5.1.7,Opera 12.15
    成功:FireFox 23,IE8

  4. Pragma: no-cache
    失败:Chrome 28,Safari 5.1.7,Opera 12.15
    成功:FireFox 23,IE8

  5. Cache-Control: no-cache
    失败:Chrome 28,Safari 5.1.7,Opera 12.15
    成功:FireFox 23,IE8

  6. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    失败:Chrome 28,Safari 5.1.7,Opera 12.15
    成功:FireFox 23,IE8

  7. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    失败:Chrome 28,Safari 5.1.7,Opera 12.15
    成功:FireFox 23,IE8

  8. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    失败:Chrome 28,Safari 5.1.7,Opera 12.15
    成功:FireFox 23,IE8

  9. Cache-Control: must-revalidate
    失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7
    成功:Opera 12.15

  10. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    <body onunload="">
    失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7
    成功:Opera 12.15

  11. Cache-Control: must-revalidate, max-age=0
    失败:Chrome 28,FireFox 23,Safari 5.1.7
    成功:IE8,Opera 12.15

  12. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Chrome 28,Safari 5.1.7
    成功:FireFox 23,IE8,Opera 12.15

  13. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Chrome 28,Safari 5.1.7
    成功:FireFox 23,IE8,Opera 12.15

  14. Cache-Control: no-store
    失败:Opera 12.15
    成功:Chrome 28,FireFox 23,IE8,Safari 5.1.7

  15. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Opera 12.15
    成功:Chrome 28,FireFox 23,IE8,Safari 5.1.7

  16. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Opera 12.15
    成功:Chrome 28,FireFox 23,IE8,Safari 5.1.7

  17. Cache-Control: private, no-cache
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    失败:Chrome 28,Safari 5.1.7,Opera 12.15
    成功:FireFox 23,IE8

  18. Cache-Control: must-revalidate
    Expires: 0
    失败:Chrome 28,FireFox 23,Safari 5.1.7,
    成功:IE8,Opera 12.15

  19. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    失败:Chrome 28,FireFox 23,Safari 5.1.7,
    成功:IE8,Opera 12.15

  20. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    失败:Chrome 28,FireFox 23,Safari 5.1.7,
    成功:IE8,Opera 12.15

  21. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    <body onunload="">
    失败:Chrome 28,FireFox 23,Safari 5.1.7,
    成功:IE8,Opera 12.15

  22. Cache-Control: private, must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    失败:Chrome 28,Safari 5.1.7
    成功:FireFox 23,IE8,Opera 12.15

  23. Cache-Control: no-store, must-revalidate
    失败:无
    成功:Chrome 28,FireFox 23,IE8,Safari 5.1.7,Opera 12.15

我发现在这个页面上的所有答案仍然有问题。 特别是,我注意到,当你通过点击后退button来访问它时,没有一个会阻止IE8使用页面的caching版本。

经过大量的研究和testing,我发现我真正需要的只有两个标题:

caching控制:无存储
变化:*

有关Vary头文件的解释,请查看http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6

在IE6-8,FF1.5-3.5,Chrome 2-3,Safari 4和Opera 9-10上,当您点击页面链接时,这些标题会导致从服务器请求页面,或者将URL直接在地址栏中。 这涵盖了截至2010年1月使用的所有浏览器中约99% 。

在IE6和Opera 9-10上,点击后退button仍然导致caching的版本被加载。 在我testing的所有其他浏览器上,他们确实从服务器获取了新版本。 到目前为止,我还没有find任何标题,这些标题会导致这些浏览器在返回button时不返回caching版本的页面。

更新:在写这个答案之后,我意识到我们的Web服务器正在将自己标识为HTTP 1.0服务器。 我列出的标题是正确的,以便来自HTTP 1.0服务器的响应不被浏览器caching。 对于HTTP 1.1服务器,请看BalusC的答案 。

我发现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> 

这里是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(); }); 

经过一番研究,我们想出了以下列表,这些列表似乎涵盖了大多数浏览器:

  • 截止date:1997年7月26日星期一05:00:00 GMT
  • Cache-Control : no-cache ,private, must-revalidate ,max-stale = 0,post-check = 0,pre-check = 0 no-store
  • Pragma :no-cache

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

 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

在回应中使用编译标题是一个妻子的故事。 RFC2616仅将其定义为请求标头

http://www.mnot.net/cache_docs/#PRAGMA

免责声明:我强烈build议阅读@ BalusC的答案。 阅读以下caching教程后: http : //www.mnot.net/cache_docs/ (我也build议您阅读它),我相信这是正确的。 但是,由于历史原因(因为我自己testing过),我将在下面列出我的原始答案:


我尝试了PHP的“接受”的答案,这不适合我。 然后我做了一点研究,find了一个小小的变体,testing了一下,结果很奏效。 这里是:

 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 MYH:i:s') . ' GMT'); header ('Pragma: no-cache'); 

这应该工作。 问题在于,当设置两次头部的相同部分时,如果false不作为头函数的第二个参数发送,头函数将简单地覆盖前一个header()调用。 所以,在设置Cache-Control ,例如,如果不想把所有参数放在一个header()函数调用中,他必须这样做:

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

查看更多完整的文档。

在IE6中有一个错误

即使使用“Cache-Control:no-cache”,也始终caching“Content-Encoding:gzip”的内容。

http://support.microsoft.com/kb/321722

您可以禁用IE6用户的gzip压缩(查看用户代理“MSIE 6”)

HTTP 1.1的RFC说适当的方法是添加一个HTTP头为:

caching控制:无caching

如果旧版浏览器与HTTP 1.1不兼容,旧版浏览器可能会忽略它。 对于那些你可以尝试标题:

Pragma:no-cache

这也适用于HTTP 1.1浏览器。

这些指令不会降低任何安全风险。 他们真的打算强制UA刷新易变的信息,而不是让UA保留信息。 看到这个类似的问题 。 至less,不能保证任何路由器,代理等都不会忽略caching指令。

更积极的一点是,有关物理访问计算机,软件安装等方面的政策将使你在安全方面领先大多数公司。 如果这些信息的消费者是公众的成员,那么唯一可以做的就是帮助他们理解,一旦信息触及他们的机器,那么这个机器就是他们的责任,而不是你的。

头文件函数的PHP文档有一个相当完整的例子(由第三方提供):

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

如果您使用IE6-IE8通过SSL下载问题,并caching:使用MS Office文件的no-cache头(以及类似的值),您可以使用caching:私有,无存储头和POST请求返回文件。 有用。

在我的情况下,我用这个修复了这个问题

 <form id="form1" runat="server" autocomplete="off"> 

当用户为安全原因点击button时,需要清除以前的表单数据的内容

通过设置Pragma:no-cache,我在所有浏览器中获得了最好和最一致的结果

在1995年将修改后的http头文件设置为某个date通常可以做到这一点。

这是一个例子:

有效期:1995年11月15日星期三04:58:08 GMT
 Last-Modified:星期三,15十一月1995 04:58:08 GMT
caching控制:无caching,必须重新validation

BalusC提供的答案中的标题不会阻止Safari 5(也可能是旧版本)在使用浏览器后退button时显示浏览器caching中的内容。 防止这种情况的一种方法是向body标签添加一个空的onunload事件处理程序属性:

 <body onunload=""> 

这个黑客明显地破坏了Safari中的后退caching: 单击后退button时是否存在跨浏览器onload事件?

接受的答案似乎不适用于IIS7 +,由于在II7中有关caching标题未被发送的大量问题:

  • 有些东西是强制响应有caching控制:在IIS7私人
  • IIS7:caching设置不工作…为什么?
  • IIS7 + ASP.NET MVC客户端caching标题不起作用
  • 为aspx页面设置caching控制
  • caching控制:无需存储,必须重新validation没有发送到IIS7 + ASP.NET MVC中的客户端浏览器

等等

接受的答案是正确的,必须设置标题,而不是必须如何设置。 这种方式适用于IIS7:

 Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.AppendCacheExtension("no-store, must-revalidate"); Response.AppendHeader("Pragma", "no-cache"); Response.AppendHeader("Expires", "-1"); 

第一行将Cache-controlno-cache ,第二行添加其他属性no-store, must-revalidate

对于ASP.NET Core,创build一个简单的中间件类:

 public class NoCacheMiddleware { private readonly RequestDelegate m_next; public NoCacheMiddleware( RequestDelegate next ) { m_next = next; } public async Task Invoke( HttpContext httpContext ) { httpContext.Response.OnStarting( ( state ) => { // ref: http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached-across-all-browsers httpContext.Response.Headers.Append( "Cache-Control", "no-cache, no-store, must-revalidate" ); httpContext.Response.Headers.Append( "Pragma", "no-cache" ); httpContext.Response.Headers.Append( "Expires", "0" ); return Task.FromResult( 0 ); }, null ); await m_next.Invoke( httpContext ); } } 

然后用Startup.cs注册它

 app.UseMiddleware<NoCacheMiddleware>(); 

确保你添加了这个地方

 app.UseStaticFiles(); 

除了标题之外,还应考虑通过https提供页面。 许多浏览器默认情况下不会cachinghttps。

 //In .net MVC [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")] public ActionResult FareListInfo(long id) { } // In .net webform <%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %> 

To complete BalusC -> ANSWER If you are using perl you can use CGI to add HTTP headers.

Using Perl:

 Use CGI; sub set_new_query() { binmode STDOUT, ":utf8"; die if defined $query; $query = CGI->new(); print $query->header( -expires => 'Sat, 26 Jul 1997 05:00:00 GMT', -Pragma => 'no-cache', -Cache_Control => join(', ', qw( private no-cache no-store must-revalidate max-age=0 pre-check=0 post-check=0 )) ); } 

Using apache httpd.conf

 <FilesMatch "\.(html|htm|js|css|pl)$"> FileETag None <ifModule mod_headers.c> Header unset ETag Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate" Header set Pragma "no-cache" Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT" </ifModule> 

Note: When I tried to use the html META, browsers ignored them and cached the page.

I just want to point out that if someone wants to prevent caching ONLY dynamic content, adding those additional headers should be made programmatically.

I edited configuration file of my project to append no-cache headers, but that also disabled caching static content, which isn't usually desirable. Modifying response headers in code assures that images and style files will be cached.

This is quite obvious, yet still worth mentioning.

And another caution. Be careful using ClearHeaders method from HttpResponse class. It may give you some bruises if you use it recklessly. Like it gave me.

After redirecting on ActionFilterAttribute event the consequences of clearing all headers are losing all session data and data in TempData storage. It's safer to redirect from an Action or don't clear headers when redirection is taking place.

On second thought I discourage all to use ClearHeaders method. It's better to remove headers separately. And to set Cache-Control header properly I'm using this code:

 filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate"); 

See this link to a Case Study on Caching:

http://securityevaluators.com/knowledge/case_studies/caching/

Summary, according to the article, only 'Cache-Control: no-store' works on Chrome, Firefox and IE. IE accepts other controls, but Chrome and Firefox do not. The link is a good read complete with the history of caching and documenting proof of concept.

I had no luck with <head><meta> elements. Adding HTTP cache related parameters directly (outside of the HTML doc) does indeed work for me.

Sample code in Python using web.py web.header calls follows. I purposefully redacted my personal irrelevant utility code.


    import web
    import sys
    import PERSONAL-UTILITIES

    myname = "main.py"

    urls = (
        '/', 'main_class'
     )

    main = web.application(urls, globals())

    render = web.template.render("templates/", base="layout", cache=False)

    class main_class(object):
        def GET(self):
            web.header("Cache-control","no-cache, no-store, must-revalidate")
            web.header("Pragma", "no-cache")
            web.header("Expires", "0")
            return render.main_form()

        def POST(self):
            msg = "POSTed:"
            form = web.input(function = None)
            web.header("Cache-control","no-cache, no-store, must-revalidate")
            web.header("Pragma", "no-cache")
            web.header("Expires", "0")
            return render.index_laid_out(greeting = msg + form.function)

    if __name__ == "__main__":
        nargs = len(sys.argv)
        # Ensure that there are enough arguments after python program name
        if nargs != 2:
            LOG-AND-DIE("%s: Command line error, nargs=%s, should be 2", myname, nargs)
        # Make sure that the TCP port number is numeric
        尝试:
            tcp_port = int(sys.argv[1])
        except Exception as e:
            LOG-AND-DIE ("%s: tcp_port = int(%s) failed (not an integer)", myname, sys.argv[1])
        # All is well!
        JUST-LOG("%s: Running on port %d", myname, tcp_port)
        web.httpserver.runsimple(main.wsgifunc(), ("localhost", tcp_port))
        main.run()

Also, just for good measure, make sure you reset the ExpiresDefault in your .htaccess file if you're using that to enable caching.

 ExpiresDefault "access plus 0 seconds" 

Afterwards, you can use ExpiresByType to set specific values for the files you want to cache:

 ExpiresByType image/x-icon "access plus 3 month" 

This may also come in handy if your dynamic files eg php, etc. are being cached by the browser, and you can't figure out why. Check ExpiresDefault .