我们如何在所有浏览器中控制网页缓存?

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

出于安全原因,我们不希望Web浏览器缓存应用程序中的某些页面曾经,。这必须至少适用于以下浏览器:

  • Internet Explorer 6+
  • Firefox 1.5+
  • Safari3+
  • Opera 9+
  • Chrome

我们的要求来自安全测试。从我们的网站注销后,您可以按下后退按钮并查看缓存的页面。

1186098 次浏览

将修改后的超文本传输协议标头设置为1995年的某个日期通常可以解决问题。

这里有一个例子:

Expires: Wed, 15 Nov 1995 04:58:08 GMTLast-Modified: Wed, 15 Nov 1995 04:58:08 GMTCache-Control: no-cache, must-revalidate

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

在ASP.NET我们使用以下代码段添加了这些:

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

来自:http://forums.asp.net/t/1013531.aspx

HTTP1.1的RFC说正确的方法是为以下内容添加HTTP标头:

缓存控制:无缓存

较旧的浏览器如果不正确兼容HTTP 1.1,可能会忽略这一点。对于那些您可以尝试标头:

Pragma:无缓存

这也适用于HTTP 1.1浏览器。

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

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

我在所有浏览器中都有最好和最一致的结果语法:无缓存

在响应中使用pragma头是一个妻子故事。RFC2616仅将其定义为请求标头

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

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


我尝试了PHP的“接受”答案,但对我不起作用。然后我做了一点研究,发现了一个轻微的变体,测试了它,它起作用了。这里是:

header('Cache-Control: no-store, private, no-cache, must-revalidate');     // HTTP/1.1header('Cache-Control: pre-check=0, post-check=0, max-age=0, max-stale = 0', false);  // HTTP/1.1header('Pragma: public');header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');                  // Date in the pastheader('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);

查看更多完整的留档这里

这些指令并没有减轻任何安全风险。它们实际上是为了强制UA刷新易失性信息,而不是阻止UA保留信息。参见这个类似的问题。至少,不能保证任何路由器、代理等也不会忽略缓存指令。

从更积极的角度来看,有关物理访问计算机、软件安装等方面的政策将使你在安全方面领先于大多数公司。如果这些信息的消费者是公众,你唯一能做的就是帮助他们理解,一旦信息到达他们的机器,那台机器是0号责任,不是你的。

除了标题之外,请考虑通过https为您的页面提供服务。默认情况下,许多浏览器不会缓存https。

我发现这个页面上的所有答案仍然有问题。特别是,我注意到当您通过点击后退按钮访问页面时,它们中没有一个会阻止IE8使用缓存版本的页面。

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

缓存控制:无存储
变量:*

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

在IE6-8、FF1.5-3.5、Chrome2-3、Safari4和Opera 9-10上,当您单击页面链接或将URL直接放在地址栏中时,这些标头会导致服务器请求页面。这涵盖了截至1月10日使用的所有浏览器中的大约0个。

在IE6和Opera 9-10上,点击后退按钮仍然会导致缓存版本被加载。在我测试的所有其他浏览器上,它们确实从服务器获取了一个新的版本。到目前为止,我还没有找到任何一组标题会导致这些浏览器在你点击后退按钮时不返回页面的缓存版本。

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

导言

适用于所有提到的客户端(和代理)的正确的最小标头集:

Cache-Control: no-cache, no-store, must-revalidatePragma: no-cacheExpires: 0

#0是针对客户端和代理的HTTP 1.1规范(Expires旁边的一些客户端隐式要求)。#2是针对史前客户端的HTTP 1.0规范。#1是针对客户端和代理的HTTP 1.0和1.1规范。在HTTP 1.1中,Cache-Control优先于Expires,所以它毕竟只适用于HTTP 1.0代理。

如果您在仅使用no-store通过HTTPS提供页面时不关心IE6及其损坏的缓存,那么您可以省略Cache-Control: no-cache

Cache-Control: no-store, must-revalidatePragma: no-cacheExpires: 0

如果您不关心IE6或HTTP 1.0客户端(HTTP 1.1于1997年推出),那么您可以省略Pragma

Cache-Control: no-store, must-revalidateExpires: 0

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

Cache-Control: no-store, must-revalidate

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

Date: Wed, 24 Aug 2016 18:32:02 GMTExpires: 0

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

如果指定了上述Cache-Control参数,则其他Cache-Control参数(例如max-age)无关紧要。如果您实际上想要缓存请求,则此处大多数其他答案中包含的#3标头只有很有趣,因此您根本不需要指定它。

如何设置?

使用PHP:

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

使用JavaServlet或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.NETWeb API:

// `response` is an instance of System.Net.Http.HttpResponseMessageresponse.Headers.CacheControl = new CacheControlHeaderValue{NoCache = true,NoStore = true,MustRevalidate = true};response.Headers.Pragma.ParseAdd("no-cache");// We can't use `response.Content.Headers.Expires` directly// since it allows only `DateTimeOffset?` values.response.Content?.Headers.TryAddWithoutValidation("Expires", 0.ToString());

使用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.NETCore v3

// using Microsoft.Net.Http.HeadersResponse.Headers[HeaderNames.CacheControl] = "no-cache, no-store, must-revalidate";Response.Headers[HeaderNames.Expires] = "0";Response.Headers[HeaderNames.Pragma] = "no-cache";

使用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:

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

使用Python/Flask:

response = make_response(render_template(...))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/Django:

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

使用Python/Pyramids:

request.response.headerlist.extend((('Cache-Control', 'no-cache, no-store, must-revalidate'),('Pragma', 'no-cache'),('Expires', '0')))

使用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.

使用Clojure(需要Ring utils):

(require '[ring.util.response :as r])(-> response(r/header "Cache-Control" "no-cache, no-store, must-revalidate")(r/header "Pragma" "no-cache")(r/header "Expires" 0))

使用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>

使用超文本标记语言:

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

超文本标记语言元标记与HTTP响应标头

重要的是要知道,当超文本标记语言页面通过HTTP连接提供时,并且HTTP响应标头和超文本标记语言<meta http-equiv>标签中存在标头两者,那么HTTP响应标头中指定的那个将优先于超文本标记语言元标记。超文本标记语言元标记仅在通过file:// URL从本地磁盘文件系统查看页面时使用。另请参阅W3超文本标记语言规范。当你不以编程方式指定它们时要小心,因为网络服务器可以包括一些默认值。

一般来说,你最好只是没有指定超文本标记语言元标记,以避免初学者混淆并依赖于硬HTTP响应标头。此外,特别是那些<meta http-equiv>标签在HTML5中是<强>无效。只允许HTML5规范中列出的http-equiv值。

验证实际的HTTP响应标头

要验证两者,您可以在Web浏览器开发人员工具集的HTTP流量监视器中查看/调试它们。您可以通过在Chrome /Firefox23+/IE9+中按F12,然后打开“网络”或“网络”选项卡面板,然后单击感兴趣的HTTP请求来发现有关HTTP请求和响应的所有详细信息来到达那里。下方截图来自Chrome:

Chrome开发人员工具集HTTP流量监视器显示stackoverflow.com上的HTTP响应标头

我也想在文件下载时设置这些标题

首先,这个问题和答案针对的是“网页”(超文本标记语言页面),而不是“文件下载”(PDF、zip、Excel等)。你最好缓存它们,并利用URI路径或查询字符串中的某个文件版本标识符来强制重新下载更改的文件。无论如何,在文件下载上应用这些无缓存标头时,在通过HTTPS而不是HTTP提供文件下载时,请注意IE7/8bug。有关详细信息,请参阅IE无法下载foo.jsf.IE无法打开此Internet站点。请求的站点不可用或找不到

(嘿,每个人:请不要盲目地复制和粘贴所有你能找到的标题)

首先,返回按钮历史记录是不是缓存

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

在旧的HTTP规范中,措辞更加强烈,明确告诉浏览器忽略后退按钮历史记录的缓存指令。

Back应该返回时间(到用户登录的时间)。它不会向前导航到以前打开的URL。

但是,在实践中,缓存可能会影响后退按钮,在非常特定的情况下:

  • 页面必须HTTPS上交付,否则,这种缓存破坏将不可靠。另外,如果您不使用HTTPS,那么您的页面很容易以许多其他方式被登录窃取。
  • 您必须发送Cache-Control: no-store, must-revalidate(一些浏览器观察no-store和一些观察must-revalidate

从未需要以下任何一项:

  • <meta>带有缓存头-它根本不起作用。完全无用。
  • post-check/pre-check-这是一个仅适用于可缓存资源的仅限IE的指令。
  • 两次或分十几个部分发送相同的标头。那里的一些PHP片段实际上替换了以前的标头,导致只发送最后一个。

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

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

奖金:新的HTTP缓存RFC

BalusC提供的答案中的标头不会阻止Safari5(可能还有旧版本)在使用浏览器的后退按钮时显示浏览器缓存中的内容。防止这种情况的一种方法是在body标记中添加一个空的onunload事件处理程序属性:

<body onunload="">

这个黑客显然破坏了Safari中的前向缓存:单击后退按钮时是否存在跨浏览器onload事件?

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

这是做同样的事情的快速/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();});

如果您面临通过SSL和缓存的IE6-IE8下载问题:MS Office文件的无缓存标头(和类似值),您可以使用缓存:私有、无存储标头和POST请求的返回文件。它有效。

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

IE6中的bug

即使您使用“Cache-Control: no-ache”,带有“Content-Encode: gzip”的内容也会始终缓存。

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

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

在我的情况下,我用这个解决了chrome中的问题

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

出于安全原因,当用户单击按钮返回时,我需要清除previus表单数据的内容

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

在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(仅限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.601.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)

结合上述内容,我们得到了适用于Chrome28、FireFox 23、IE8、Safari5.1.7和Opera 12.15的解决方案:Cache-Control: no-store, must-revalidate(仅限https)

请注意,需要https是因为Opera不会停用纯超文本传输协议页面的历史缓冲区。如果您真的无法获得https并且准备忽略Opera,最好的做法是:

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

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

超文本传输协议:

  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
    成功:Chrome28,FireFox 23,IE8,Safari5.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
    成功:Chrome28,FireFox 23,IE8,Safari5.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: *
    失败:Safari5.1.7, Opera 12.15
    成功:Chrome28,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: *
    失败:Safari5.1.7, Opera 12.15
    成功:Chrome28,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="">
    失败:Chrome28, FireFox 23,Safari5.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="">
    失败:Chrome28, FireFox 23,Safari5.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="">
    失败:Chrome28, FireFox 23,Safari5.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="">
    失败:Chrome28, FireFox 23,Safari5.1.7, Opera 12.15
    成功:IE8

  9. Cache-Control: no-store
    失败:Safari5.1.7, Opera 12.15
    成功:Chrome28,FireFox 23,IE8

  10. Cache-Control: no-store
    <body onunload="">
    失败:Opera 12.15
    成功:Chrome28,FireFox 23,IE8,Safari5.1.7

  11. Cache-Control: no-cache
    失败:Chrome28, FireFox 23,Safari5.1.7, Opera 12.15
    成功:IE8

  12. Vary: *
    失败:Chrome28, FireFox 23, IE8,Safari5.1.7, Opera 12.15
    成功:无

  13. Pragma: no-cache
    失败:Chrome28, FireFox 23, IE8,Safari5.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="">
    失败:Chrome28, FireFox 23,Safari5.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="">
    失败:Chrome28, FireFox 23,Safari5.1.7, Opera 12.15
    成功:IE8

  16. Cache-Control: must-revalidate, max-age=0
    失败:Chrome28, FireFox 23,Safari5.1.7, Opera 12.15
    成功:IE8

  17. Cache-Control: must-revalidate
    Expires: 0
    失败:Chrome28, FireFox 23,Safari5.1.7, Opera 12.15
    成功:IE8

  18. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    失败:Chrome28, FireFox 23,Safari5.1.7, Opera 12.15
    成功:IE8

  19. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    失败:Chrome28, FireFox 23, IE8,Safari5.1.7, Opera 12.15
    成功:无

HTTPS:

  1. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    失败:Chrome28, FireFox 23, IE8,Safari5.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="">
    失败:Chrome28, FireFox 23, IE8,Safari5.1.7, Opera 12.15
    成功:无

  3. Vary: *
    失败:Chrome28,Safari5.1.7, Opera 12.15
    成功:FireFox 23、IE8

  4. Pragma: no-cache
    失败:Chrome28,Safari5.1.7, Opera 12.15
    成功:FireFox 23、IE8

  5. Cache-Control: no-cache
    失败:Chrome28,Safari5.1.7, Opera 12.15
    成功:FireFox 23、IE8

  6. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    失败:Chrome28,Safari5.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: *
    失败:Chrome28,Safari5.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: *
    失败:Chrome28,Safari5.1.7, Opera 12.15
    成功:FireFox 23、IE8

  9. Cache-Control: must-revalidate
    失败:Chrome28, FireFox 23, IE8,Safari5.1.7
    成功:Opera 12.15

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

  11. Cache-Control: must-revalidate, max-age=0
    失败:Chrome28, FireFox 23,Safari5.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="">
    失败:Chrome28,Safari5.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="">
    失败:Chrome28,Safari5.1.7
    成功:FireFox 23、IE8、Opera 12.15

  14. Cache-Control: no-store
    失败:Opera 12.15
    成功:Chrome28,FireFox 23,IE8,Safari5.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
    成功:Chrome28,FireFox 23,IE8,Safari5.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
    成功:Chrome28,FireFox 23,IE8,Safari5.1.7

  17. Cache-Control: private, no-cache
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    失败:Chrome28,Safari5.1.7, Opera 12.15
    成功:FireFox 23、IE8

  18. Cache-Control: must-revalidate
    Expires: 0
    失败:Chrome28, FireFox 23,Safari5.1.7,
    成功:IE8,Opera 12.15

  19. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    失败:Chrome28, FireFox 23,Safari5.1.7,
    成功:IE8,Opera 12.15

  20. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    失败:Chrome28, FireFox 23,Safari5.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="">
    失败:Chrome28, FireFox 23,Safari5.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: *
    失败:Chrome28,Safari5.1.7
    成功:FireFox 23、IE8、Opera 12.15

  23. Cache-Control: no-store, must-revalidate
    失败:无
    成功:Chrome28,FireFox 23,IE8,Safari5.1.7,Opera 12.15

完成BalusC->ANSWER如果您使用perl,您可以使用CGI添加HTTP标头。

使用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(privateno-cacheno-storemust-revalidatemax-age=0pre-check=0post-check=0)));}

使用apachehttpd.conf

<FilesMatch "\.(html|htm|js|css|pl)$">FileETag None<ifModule mod_headers.c>Header unset ETagHeader 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>

备注:当我尝试使用html META时,浏览器忽略了它们并缓存了页面。

接受的答案似乎不适用于IIS7+,因为有大量关于缓存标头未在II7中发送的问题:

如此等等

接受的答案是正确的,必须设置标头,但不能设置它们的方式。这种方式适用于IIS7:

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

第一行将Cache-control设置为no-cache,第二行添加其他属性no-store, must-revalidate

我只是想指出,如果有人想阻止只缓存动态内容,则应以编程方式添加这些附加标头。

我编辑了项目的配置文件以附加无缓存标头,但这也禁用了缓存静态内容,这通常是不可取的。在代码中修改响应标头可确保缓存图像和样式文件。

这是显而易见的,但仍然值得一提。

还有另一个警告。小心使用HttpResponse类中的ClearHeaders方法。如果你鲁莽地使用它,它可能会给你一些瘀伤。就像它给我的一样。

在ActionFilterAt的事件上重定向后,清除所有标头的后果是丢失TempData存储中的所有会话数据和数据。在发生重定向时,从Action重定向或不清除标头更安全。

经过仔细考虑,我不鼓励所有人使用ClearHeaders方法。最好单独删除标头。为了正确设置Cache-Control标头,我使用以下代码:

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

请参阅此链接到缓存案例研究:

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

总结,根据这篇文章,只有Cache-Control: no-store适用于Chrome,Firefox和IE。IE接受其他控件,但Chrome和Firefox不接受。该链接是一个很好的阅读,完整的缓存和文档概念证明的历史。

对于ASP.NETCore,创建一个简单的中间件类:

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-browsershttpContext.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();

我对<head><meta>元素没有运气。直接添加HTTP缓存相关参数(在超文本标记语言文档之外)确实对我有用。

下面是使用web.pyweb.header调用的Python示例代码。

import webimport sysimport 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 nameif nargs != 2:LOG-AND-DIE("%s: Command line error, nargs=%s, should be 2", myname, nargs)# Make sure that the TCP port number is numerictry: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()

此外,为了更好地衡量,如果您使用ExpiresDefault来启用缓存,请确保您重置.htaccess文件中的ExpiresDefault

ExpiresDefault "access plus 0 seconds"

之后,您可以使用ExpiresByType为要缓存的文件设置特定值:

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

如果您的动态文件(例如php等)被浏览器缓存,并且您不知道原因,这也可能派上用场。检查ExpiresDefault

您可以使用位置块在IIS中设置单个文件而不是整个应用程序获取缓存

 <location path="index.html"><system.webServer><httpProtocol><customHeaders><add name="Cache-Control" value="no-cache" /></customHeaders></httpProtocol></system.webServer></location>

不确定我的答案听起来是否简单而愚蠢,也许很久以前你就已经知道了,但由于阻止某人使用浏览器后退按钮查看您的历史页面是你的目标之一,你可以使用:

window.location.replace("https://www.example.com/page-not-to-be-viewed-in-browser-history-back-button.html");

当然,这可能无法在整个站点上实现,但至少对于一些关键页面,您可以这样做。希望这有帮助。

我就这样解决了。

2个考虑因素:

1)服务器端事件不会在后退单击时触发,而不是JavaScript。

2)我有2个javascript来读/写cookie

function setCookie(name, value, days){var expires = "";if (days){var date = new Date();date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));expires = "; expires=" + date.toUTCString();}document.cookie = name + "=" + (value || "") + expires + "; path=/";}
function getCookie(name){var nameEQ = name + "=";var ca = document.cookie.split(';');
for (var i = ca.length - 1; i >= 0; i--){var c = ca[i];while (c.charAt(0) == ' '){c = c.substring(1, c.length);}
if (c.indexOf(nameEQ) == 0){return c.substring(nameEQ.length, c.length);}}return null;}

在我的Page_Load我插入了这个:(这不是在点击后触发)

    protected void Page_Load(object sender, EventArgs e){Page.RegisterClientScriptBlock("", "<script>setCookie('" + Session.SessionID + "', '" + Login + "', '100');</script>");}

其中'Login'是我的id值,在注销后为-1(您可以使用其他东西,例如布尔值)。

然后在我的页面中,我添加了这个:(这是在点击后触发的)

<script type="text/javascript">if (getCookie('<%= Session.SessionID %>') < 0){if (history.length > 0){history.go(+1);}}
</script>

没有别的了。

使用此解决方案,在每个页面上启用反向单击,并且仅在同一浏览器上的每个页面注销后才禁用。