协慌网

登录 贡献 社区

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

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

出于安全原因,我们不希望在我们的应用程序某些网页缓存, 有史以来,通过 Web 浏览器。这必须至少适用于以下浏览器:

  • Internet Explorer 6+
  • Firefox 1.5+
  • Safari 3+
  • Opera 9+

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

答案

介绍

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

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 提供仅使用no-store页面时不关心 IE6 及其损坏的缓存,那么您可以省略Cache-Control: no-cache

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

如果您不关心 IE6 和 HTTP 1.0 客户端(1997 年引入 HTTP 1.1),那么您可以省略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参数,则其他Cache-Control参数(例如max-age是无关紧要的。此处大多数其他答案中包含的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:

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 / Pyramid:

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

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值。

验证实际的 HTTP 响应标头

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

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

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

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

(嘿,大家:请不要盲目地复制并粘贴你能找到的所有标题)

首先, 后退按钮历史记录不是缓存

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

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

回到应该回到过去(到时候用户登录)。它不会向前导航到先前打开的 URL。

但是,实际上,在非常特定的情况下,缓存可以影响后退按钮:

  • 页面必须通过HTTPS 提供 ,否则此缓存破坏将不可靠。另外,如果您不使用 HTTPS,那么您的页面很容易受到许多其他方式的登录窃取。
  • 你必须发送Cache-Control: no-store, must-revalidate (某些浏览器观察no-store ,有些观察must-revalidate

永远不需要任何:

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

如果需要,可以添加:

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

奖励: 新的 HTTP 缓存 RFC

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

在 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
    html 中的<body onunload="">

  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)

结合上述内容为我们提供了适用于 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="">

Below shows the raw logs of my tests:

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="">
    Fail: Opera 12.15
    Success: 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="">
    Fail: Opera 12.15
    Success: 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: *
    Fail: Safari 5.1.7, Opera 12.15
    Success: 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: *
    Fail: Safari 5.1.7, Opera 12.15
    Success: 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="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: 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="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: 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="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: 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="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  9. Cache-Control: no-store
    Fail: Safari 5.1.7, Opera 12.15
    Success: Chrome 28, FireFox 23, IE8

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

  11. Cache-Control: no-cache
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  12. Vary: *
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Success: none

  13. Pragma: no-cache
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Success: none

  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="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: 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="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  16. Cache-Control: must-revalidate, max-age=0
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  17. Cache-Control: must-revalidate
    Expires: 0
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

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

  19. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Success: none

HTTPS:

  1. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Success: none

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

  3. Vary: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  4. Pragma: no-cache
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  5. Cache-Control: no-cache
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

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

  7. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: 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: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  9. Cache-Control: must-revalidate
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7
    Success: Opera 12.15

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

  11. Cache-Control: must-revalidate, max-age=0
    Fail: Chrome 28, FireFox 23, Safari 5.1.7
    Success: 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="">
    Fail: Chrome 28, Safari 5.1.7
    Success: 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="">
    Fail: Chrome 28, Safari 5.1.7
    Success: FireFox 23, IE8, Opera 12.15

  14. Cache-Control: no-store
    Fail: Opera 12.15
    Success: 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="">
    Fail: Opera 12.15
    Success: 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="">
    Fail: Opera 12.15
    Success: 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: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  18. Cache-Control: must-revalidate
    Expires: 0
    Fail: Chrome 28, FireFox 23, Safari 5.1.7,
    Success: IE8, Opera 12.15

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

  20. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7,
    Success: 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="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7,
    Success: IE8, Opera 12.15

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

  23. Cache-Control: no-store, must-revalidate
    Fail: none
    Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15