我们的调查表明,并非所有浏览器都以统一的方式遵守HTTP缓存指令。
出于安全原因,我们不希望Web浏览器永远缓存应用程序中的某些页面。这必须至少适用于以下浏览器:
- Internet Explorer 6+
- Firefox 1.5以上
- Safari 3+
- 歌剧9+
- 铬
我们的要求来自安全测试。从我们的网站注销后,您可以按返回按钮并查看缓存的页面。
我们的调查表明,并非所有浏览器都以统一的方式遵守HTTP缓存指令。
出于安全原因,我们不希望Web浏览器永远缓存应用程序中的某些页面。这必须至少适用于以下浏览器:
我们的要求来自安全测试。从我们的网站注销后,您可以按返回按钮并查看缓存的页面。
Answers:
适用于所有提到的客户端(和代理)的正确的最小标头集:
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代理。
如果仅通过HTTPS提供页面时,如果您不在意IE6及其缓存中断no-store
,则可以省略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
但这可能会失败,例如,如果最终用户操纵了操作系统日期,而客户端软件则依赖它。
如果指定了上述参数,则其他Cache-Control
参数如max-age
无关紧要Cache-Control
。仅当您确实要缓存请求时,Last-Modified
此处大多数其他答案中包含的标头才是有趣的,因此根本不需要指定它。
使用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 Web API:
// `response` is an instance of System.Net.Http.HttpResponseMessage
response.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.NET Core v3
// using Microsoft.Net.Http.Headers
Response.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或Python / Flask:
headers["Cache-Control"] = "no-cache, no-store, must-revalidate" # HTTP 1.1.
headers["Pragma"] = "no-cache" # HTTP 1.0.
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 /金字塔:
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.
使用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">
重要的是要知道,当通过HTTP连接为HTML页面提供服务,并且HTTP响应标头和HTML 标记中都存在标头时<meta http-equiv>
,则HTTP响应标头中指定的标头将优先于HTML meta标记。仅当通过file://
URL 从本地磁盘文件系统查看页面时,才使用HTML元标记。另请参阅W3 HTML规范第5.2.2章。当您不以编程方式指定它们时,请务必小心,因为Web服务器可以包含一些默认值。
通常,最好不要指定HTML元标记,以免引起初学者的困惑并依赖硬HTTP响应标头。此外,尤其是这些<meta http-equiv>
标记在HTML5 中无效。仅允许HTML5规范中http-equiv
列出的值。
要验证彼此,可以在webbrowser开发人员工具集的HTTP流量监视器中查看/调试它们。您可以通过在Chrome / Firefox23 + / IE9 +中按F12,然后打开“网络”或“网络”标签面板,然后单击感兴趣的HTTP请求以发现有关HTTP请求和响应的所有详细信息,来到达那里。在下面的截图是从Chrome中:
首先,此问题和答案针对“网页”(HTML页面),而不是“文件下载”(PDF,zip,Excel等)。您最好将它们缓存起来,并在URI路径或querystring中的某个位置使用一些文件版本标识符,以强制在更改的文件上重新下载。无论如何,当在文件下载上应用这些无缓存头时,请注意在通过HTTPS(而非HTTP)提供文件下载时的IE7 / 8错误。有关详细信息,请参见IE无法下载foo.jsf。IE无法打开此网站。所请求的站点不可用或找不到。
(嘿,大家:请不要随便复制并粘贴所有可以找到的标头)
首先,“ 后退”按钮历史记录不是缓存:
新鲜度模型(第4.2节)不一定适用于历史记录机制。也就是说,历史记录机制即使已过期也可以显示先前的表示。
在旧的HTTP规范中,措词甚至更强,明确告诉浏览器对于后退按钮历史记录忽略高速缓存指令。
回到应该回到过去(到时候用户在登录)。它不会向前导航到先前打开的URL。
但是,实际上,在非常特殊的情况下,缓存会影响后退按钮:
Cache-Control: no-store, must-revalidate
(某些浏览器遵守no-store
,有些则遵守must-revalidate
)您永远不需要:
<meta>
带有缓存头的文件-根本不起作用。完全没用。post-check
/ pre-check
—这是仅适用于achable的IE指令资源。如果需要,可以添加:
no-cache
或max-age=0
,这将使资源(URL)“陈旧”,并要求浏览器向服务器检查是否有较新的版本(no-store
已经暗示它会更强大)。Expires
HTTP / 1.0客户端的日期为过去的日期(尽管现在完全不存在真正的 HTTP / 1.0客户端)。奖励:新的HTTP缓存RFC。
Cache-Control: must-revalidate
。为什么不发送Cache-Control: no-cache
就no-cache
已经暗示了must-revalidate
?w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1
如@Kornel所述,您想要的不是停用缓存,而是停用历史记录缓冲区。不同的浏览器有自己的微妙方式来禁用历史记录缓冲区。
在Chrome(v28.0.1500.95 m)中,我们只能通过进行此操作Cache-Control: no-store
。
在FireFox(v23.0.1)中,以下任何一种均可工作:
Cache-Control: no-store
Cache-Control: no-cache
(仅https)
Pragma: no-cache
(仅https)
Vary: *
(仅https)
在Opera(v12.15)中,我们只能通过Cache-Control: must-revalidate
(仅https)来执行此操作。
在Safari(v5.1.7,7534.57.2)中,以下任何一种均可使用:
Cache-Control: no-store
<body onunload="">
在HTML
Cache-Control: no-store
(仅https)
在IE8(v8.0.6001.18702IC)中,以下任何一种均可工作:
Cache-Control: must-revalidate, max-age=0
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: must-revalidate
Expires: 0
Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
(仅https)
Vary: *
(仅https)
结合以上内容,我们就能获得适用于Chrome 28,FireFox 23,IE8,Safari 5.1.7和Opera 12.15的解决方案:( Cache-Control: no-store, must-revalidate
仅适用于https)
请注意,需要https,因为Opera不会为纯HTTP页面停用历史记录缓冲区。如果您确实无法获取https并准备忽略Opera,那么您可以做的最好的事情是:
Cache-Control: no-store
<body onunload="">
下面显示了我的测试的原始日志:
HTTP:
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
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
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
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
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
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
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
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
Cache-Control: no-store
失败:Safari 5.1.7,Opera 12.15
成功:Chrome 28,FireFox 23,IE8
Cache-Control: no-store
<body onunload="">
失败:Opera 12.15
成功:Chrome 28,FireFox 23,IE8,Safari 5.1.7
Cache-Control: no-cache
失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
成功:IE8
Vary: *
失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7,Opera 12.15
成功:无
Pragma: no-cache
失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7,Opera 12.15
成功:无
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
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
Cache-Control: must-revalidate, max-age=0
失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
成功:IE8
Cache-Control: must-revalidate
Expires: 0
失败:Chrome 28,FireFox 23,Safari 5.1.7,Opera 12.15
成功:IE8
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
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:
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
成功:无
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
成功:无
Vary: *
失败:Chrome 28,Safari 5.1.7,Opera 12.15
成功:FireFox 23,IE8
Pragma: no-cache
失败:Chrome 28,Safari 5.1.7,Opera 12.15
成功:FireFox 23,IE8
Cache-Control: no-cache
失败:Chrome 28,Safari 5.1.7,Opera 12.15
成功:FireFox 23,IE8
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
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
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
Cache-Control: must-revalidate
失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7
成功:Opera 12.15
Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
<body onunload="">
失败:Chrome 28,FireFox 23,IE8,Safari 5.1.7
成功:Opera 12.15
Cache-Control: must-revalidate, max-age=0
失败:Chrome 28,FireFox 23,Safari 5.1.7
成功:IE8,Opera 12.15
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
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
Cache-Control: no-store
失败:Opera 12.15
成功:Chrome 28,FireFox 23,IE8,Safari 5.1.7
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
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
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
Cache-Control: must-revalidate
Expires: 0
失败:Chrome 28,FireFox 23,Safari 5.1.7,
成功:IE8,Opera 12.15
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
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
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
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
Cache-Control: no-store, must-revalidate
失败:无
成功:Chrome 28,FireFox 23,IE8,Safari 5.1.7,Opera 12.15
<body onunload="">
但似乎更像解决实际问题的一种方法。我尝试使用.htaccess并以这种方式修改标头,如果使用HTTPS,它应该以这种方式工作吗?问题最多的主要是野生动物园。
Cache-Control: no-store
。<body onunload="">
仅当您没有HTTPS时才需要。
我发现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();
});
我发现此页面上的所有答案仍然存在问题。特别是,我注意到当您通过单击“后退”按钮访问IE8时,它们都无法阻止IE8使用该页面的缓存版本。
经过大量的研究和测试,我发现我真正需要的仅有两个标头是:
缓存控制:不存储
Vary:*
有关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时,这些标题导致从服务器请求页面直接在地址栏中。约占99%截至2010年1月,使用中的所有浏览器的。
在IE6和Opera 9-10上,单击“后退”按钮仍会导致加载缓存的版本。在我测试过的所有其他浏览器上,它们确实从服务器获取了一个新版本。到目前为止,我还没有找到任何可以使这些浏览器在您按下“后退”按钮时不返回页面的缓存版本的标头集。
更新: 写下此答案后,我意识到我们的Web服务器将自己标识为HTTP 1.0服务器。我列出的标头是正确的标头,以便浏览器不会缓存来自HTTP 1.0服务器的响应。对于HTTP 1.1服务器,请查看BalusC的答案。
经过一些研究,我们得出了以下标题列表,这些标题似乎涵盖了大多数浏览器:
在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
Cache-Control: no-cache
与Cache-Control: private
冲突-永远都不要在一起:前者告诉浏览器和代理根本不要缓存,后者告诉代理不要缓存,但让浏览器保留自己的私有副本。我不确定浏览器将遵循哪个设置,但是浏览器和版本之间不太可能保持一致。
响应中使用pragma标头是一个妻子的故事。RFC2616仅将其定义为请求标头
免责声明:我强烈建议阅读@BalusC的答案。阅读以下缓存教程后: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);
在此处查看更多完整的文档。
对于ASP.NET Core,创建一个简单的中间件类:
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();
IE6中有一个错误
即使使用“ Cache-Control:no-cache”,也会始终缓存带有“ Content-Encoding:gzip”的内容。
http://support.microsoft.com/kb/321722
您可以为IE6用户禁用gzip压缩(检查用户代理中的“ MSIE 6”)
HTTP 1.1的RFC表示正确的方法是为以下项添加HTTP标头:
缓存控制:无缓存
如果较旧的浏览器不正确符合HTTP 1.1,则可能会忽略此设置。对于那些,您可以尝试标题:
语法:无缓存
这也应该适用于HTTP 1.1浏览器。
通常在1995年将修改后的http标头设置为某个日期即可。
这是一个例子:
过期:1995年11月15日星期三格林尼治标准时间 上次修改时间:1995年11月15日,星期三,格林尼治标准时间 缓存控制:无缓存,必须重新验证
header('Pragma: public');
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header('Last-Modified: '.gmdate('D, d M Y H: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);
接受的答案似乎不适用于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
Response.Cache.SetAllowResponseInBrowserHistory(false); Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.SetNoStore(); Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
使用浏览器的后退按钮时,BalusC提供的答案中的标题不会阻止Safari 5(可能还包括旧版本)显示来自浏览器缓存的内容。防止这种情况的一种方法是向body标签添加一个空的onunload事件处理程序属性:
<body onunload="">
此黑客显然破坏了Safari中的后退缓存:单击“后退”按钮时是否存在跨浏览器的onload事件?
完成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(
private
no-cache
no-store
must-revalidate
max-age=0
pre-check=0
post-check=0
))
);
}
使用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>
注意:当我尝试使用html META时,浏览器将其忽略并缓存页面。
我只想指出,如果有人想防止仅缓存动态内容,则应以编程方式添加这些其他标头。
我编辑了项目的配置文件以追加无缓存头,但是这也禁用了缓存静态内容的功能,这通常是不希望的。修改代码中的响应标头可确保图像和样式文件将被缓存。
这是很明显的,但仍然值得一提。
还有另一个警告。使用HttpResponse类中的ClearHeaders方法时要小心。如果您不计后果地使用它,可能会给您带来一些挫伤。就像它给了我。
在ActionFilterAttribute事件上重定向后,清除所有标头的后果将丢失所有会话数据和TempData存储中的数据。从Action重定向或进行重定向时不清除标头是比较安全的。
再次考虑,我不鼓励所有人使用ClearHeaders方法。最好单独删除标题。为了正确设置Cache-Control标头,我使用以下代码:
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");
我没有运气 <head><meta>
。实际上,直接添加HTTP缓存相关参数(在HTML文档之外)对我确实有用。
web.header
以下是使用web.py 调用的Python示例代码。我故意编辑了与个人无关的实用程序代码。
导入网站 导入系统 进口个人工具 myname =“ main.py” 网址=( '/','main_class' ) main = web.application(urls,globals()) render = web.template.render(“ templates /”,base =“ layout”,cache = False) 类main_class(object): def GET(): web.header(“缓存控制”,“无缓存,无存储,必须重新验证”) web.header(“ Pragma”,“ no-cache”) web.header(“ Expires”,“ 0”) 返回render.main_form() def POST(自己): msg =“已发布:” 形式= web.input(功能=无) web.header(“缓存控制”,“无缓存,无存储,必须重新验证”) web.header(“ Pragma”,“ no-cache”) web.header(“ Expires”,“ 0”) 返回render.index_laid_out(问候= msg + form.function) 如果__name__ ==“ __main__”: nargs = len(sys.argv) #确保python程序名称后有足够的参数 如果nargs!= 2: LOG-AND-DIE(“%s:命令行错误,nargs =%s,应为2”,myname,nargs) #确保TCP端口号是数字 尝试: tcp_port = int(sys.argv [1]) 例外,例如e: LOG-AND-DIE(“%s:tcp_port = int(%s)失败(不是整数)”,我的名字,sys.argv [1]) # 一切都很好! JUST-LOG(“%s:在端口%d上运行”,myname,tcp_port) web.httpserver.runsimple(main.wsgifunc(),(“ localhost”,tcp_port)) main.run()
请参阅此链接以获取有关缓存的案例研究:
http://securityevaluators.com/knowledge/case_studies/caching/
摘要,根据这篇文章,仅Cache-Control: no-store
适用于Chrome,Firefox和IE。IE接受其他控件,但Chrome和Firefox不接受。该链接是一本很好的阅读文章,其中包含缓存的历史记录和概念证明文档。