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

时间:2008-09-08 12:08:49

标签: http caching https http-headers

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

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

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

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

29 个答案:

答案 0 :(得分:2355)

简介

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

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代理。

如果您在仅使用no-store通过HTTPS投放网页时不关心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参数,则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:

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 spec chapter 5.2.2。如果不以编程方式指定它们,请注意这一点,因为Web服务器可以包含一些默认值。

通常情况下,您最好只指定HTML元标记以避免启动者混淆,并依赖于硬HTTP响应标头。此外,具体而言,HTML5中的<meta http-equiv>代码为invalid。只允许HTML5 specification中列出的http-equiv值。

验证实际的HTTP响应标头

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

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

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

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

答案 1 :(得分:224)

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

首先,Back button history is not a cache

  

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

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

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

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

  • Page 必须通过 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,这会使资源(网址)“陈旧”,并且要求浏览器检查服务器是否有更新的版本(no-store已经暗示这更强大)
  • Expires,其中包含过去HTTP / 1.0客户端的日期(尽管真正的仅限HTTP / 1.0的客户端现在完全不存在。)

奖金:The new HTTP caching RFC

答案 2 :(得分:94)

正如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)

  5. 在Opera(v12.15)中,我们只能通过Cache-Control: must-revalidate(仅限https)执行此操作。

    在Safari(v5.1.7,7534.57.2)中,任何一个都可以使用:

    1. Cache-Control: no-store 在{html

    2. <body onunload="">
    3. Cache-Control: no-store(仅限https)

    4. 在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)

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

        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
          成功:无

        20. <强> 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

答案 3 :(得分:32)

我发现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();
});

答案 4 :(得分:25)

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

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

  

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

有关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上,点击后退按钮仍会导致加载缓存版本。在我测试的所有其他浏览器上,他们确实从服务器获取了一个新版本。到目前为止,我还没有找到任何一组标题,当您点击后退按钮时,这些标题会导致这些浏览器不返回页面的缓存版本。

更新:写完这个答案后,我意识到我们的网络服务器将自己标识为HTTP 1.0服务器。我列出的标题是正确的,以便HTTP 1.0服务器的响应不被浏览器缓存。对于HTTP 1.1服务器,请查看BalusC的answer

答案 5 :(得分:19)

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

在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

答案 6 :(得分:8)

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

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

答案 7 :(得分:8)

免责声明:我强烈建议阅读@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);

查看更完整的文档here

答案 8 :(得分:7)

对于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();

答案 9 :(得分:7)

IE6中存在错误

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

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

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

答案 10 :(得分:6)

如果您遇到IE6-IE8 over SSL和缓存的下载问题:使用MS Office文件的no-cache标头(和类似的值),您可以在POST请求中使用cache:private,no-store标头和返回文件。有用。

答案 11 :(得分:6)

在我的情况下,我使用此

解决了Chrome中的问题
<form id="form1" runat="server" autocomplete="off">

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

答案 12 :(得分:6)

将修改后的http标头设置为1995年的某个日期通常可以解决问题。

以下是一个例子:

Expires: Wed, 15 Nov 1995 04:58:08 GMT
Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
Cache-Control: no-cache, must-revalidate

答案 13 :(得分:6)

这些指令不会降低任何安全风险。它们实际上是为了迫使UA刷新易变信息,而不是让UA不保留信息。见this similar question。至少,不能保证任何路由器,代理等也不会忽略缓存指令。

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

答案 14 :(得分:6)

PHP documentation for the header function有一个相当完整的例子(由第三方提供):

    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);

答案 15 :(得分:6)

HTTP 1.1的RFC说正确的方法是为:

添加HTTP标头

缓存控制:无缓存

如果老浏览器不正确地符合HTTP 1.1,则可能会忽略此问题。对于那些你可以尝试标题:

Pragma:no-cache

这也适用于HTTP 1.1浏览器。

答案 16 :(得分:4)

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

<body onunload=""> 

这个hack显然打破了Safari中的后向缓存:Is there a cross-browser onload event when clicking the back button?

答案 17 :(得分:4)

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

答案 18 :(得分:4)

接受的答案似乎不适用于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

答案 19 :(得分:4)

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

ExpiresDefault "access plus 0 seconds"

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

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

如果您的动态文件例如,这也可能会派上用场php等正在被浏览器缓存,你无法弄清楚原因。检查ExpiresDefault

答案 20 :(得分:3)

除了标题之外,请考虑通过 https 投放您的网页。许多浏览器默认不会缓存https。

答案 21 :(得分:3)

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

// In .net webform
<%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %>

答案 22 :(得分:2)

完成BalusC - &gt; 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时,浏览器会忽略它们并缓存页面。

答案 23 :(得分:0)

我只是想指出,如果有人想要阻止仅缓存动态内容,那么应该以编程方式添加这些额外的标头。

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

这很明显,但仍值得一提。

另一个警告。小心使用HttpResponse类中的ClearHeaders方法。如果你鲁莽地使用它可能会给你一些伤痕。喜欢它给了我。

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

第二个想法我不鼓励所有人使用ClearHeaders方法。最好分开删除标题。并正确设置Cache-Control标头我正在使用此代码:

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

答案 24 :(得分:0)

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

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

摘要,根据文章,只有Cache-Control: no-store适用于Chrome,Firefox和IE。 IE接受其他控件,但Chrome和Firefox不接受。该链接是一个很好的阅读,包括缓存和记录概念证明的历史。

答案 25 :(得分:0)

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

使用web.py web.header调用的Python示例代码如下。我故意编辑了我个人不相关的实用程序代码。


    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
        try:
            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()

答案 26 :(得分:0)

我已经用这种方式解决了。

2个注意事项:

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

2)我有2个可读写cookie的javascript

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>");
    }

其中“登录”是我的id值,该值在注销后为-1(您可以使用其他值,例如布尔值)。

然后在我的页面中添加了此内容:(此点击后会触发)

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

</script>

没什么

使用此解决方案,在每个页面上启用后单击,只有在使用同一浏览器注销每个页面后才禁用。

答案 27 :(得分:-1)

您可以使用位置块来设置单个文件,而不是整个应用程序都在IIS中进行缓存

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

答案 28 :(得分:-2)

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

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

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