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

How to control web page caching, across all browsers?

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

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

  • Internet Explorer 6+
  • 火狐1.5 +
  • 狩猎3号
  • 歌剧9 +

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


介绍

在所有提到的客户机(和代理)上工作的正确的最小头集:

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

Cache-Control符合客户机和代理的HTTP 1.1规范(并且在Expires旁边的一些客户机隐式要求)。Pragma符合用于史前客户机的HTTP 1.0规范。Expires是根据客户机和代理的HTTP1.0和1.1规范提供的。在HTTP 1.1中,Cache-Control优先于Expires,因此它毕竟只适用于HTTP 1.0代理。

如果你不关心IE6和它的坏缓存,而只使用no-store通过https服务页面,那么你可以省略Cache-Control: no-cache

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

如果您不关心IE6或HTTP1.0客户机(HTTP1.1是1997年推出的),那么可以省略Pragma

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

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

1
Cache-Control: no-store, must-revalidate

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

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

但如果最终用户操纵操作系统日期,而客户机软件依赖于操作系统日期,则可能会失败。

如果指定了上述Cache-Control参数,则其他Cache-Control参数(如max-age参数)不相关。这里大多数其他答案中包含的Last-Modified头只有在您实际想要缓存请求时才有意思,因此您根本不需要指定它。

如何设置?

使用PHP:

1
2
3
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:

1
2
3
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

1
2
3
4
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:

1
2
3
4
5
6
7
8
9
10
11
// `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:

1
2
3
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:

1
2
3
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:

1
2
3
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:

1
2
3
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:

1
2
3
4
5
6
7
request.response.headerlist.extend(
    (
        ('Cache-Control', 'no-cache, no-store, must-revalidate'),
        ('Pragma', 'no-cache'),
        ('Expires', '0')
    )
)

使用GO:

1
2
3
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文件:

1
2
3
4
5
<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:

1
2
3
<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响应头

重要的是要知道,当一个HTML页面通过HTTP连接提供服务,并且在HTTP响应头和HTML 标记中都存在一个头时,HTTP响应头中指定的头将优先于HTML元标记。HTML元标记仅在通过file://URL从本地磁盘文件系统查看页面时使用。另请参见W3 HTML规范第5.2.2章。当您不以编程方式指定它们时,请注意这一点,因为Web服务器也可以包括一些默认值。

一般来说,最好不要指定HTML元标记,以避免初学者混淆,并依赖硬HTTP响应头。此外,特别是那些标签在HTML5中无效。仅允许HTML5规范中列出的http-equiv值。

验证实际的HTTP响应头

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

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

我也要在文件下载时设置这些头文件

首先,这个问题和答案的目标是"网页"(HTML页面),而不是"文件下载"(PDF、Zip、Excel等)。最好将它们缓存,并在URI路径或querystring中的某个位置使用某个文件版本标识符,以强制对更改的文件重新下载。当在文件下载中应用那些没有缓存的头文件时,那么在通过HTTPS而不是HTTP提供文件下载服务时要注意IE7/8错误。有关详细信息,请参阅ie cannot download foo.jsf。IE无法打开此Internet站点。请求的站点不可用或找不到。


(嘿,各位:请不要盲目复制和粘贴所有可以找到的邮件头)

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

The freshness model (Section 4.2) does not necessarily apply to history mechanisms. That is, a history mechanism can display a previous representation even if it has expired.

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

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

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

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

你永远不需要:

  • 带缓存头的-根本不起作用。完全没用。
  • post-checkpre-check-这是仅适用于可计算资源的指令。
  • 发送同一个标题两次或分十二部分。一些PHP代码片段实际上替换了前面的头,结果只发送了最后一个。

如果需要,可以添加:

  • no-cachemax-age=0,这将使资源(url)变得"过时",并要求浏览器在有更新版本的情况下与服务器进行检查(no-store已经暗示这一点更为强大)。
  • Expires中有一个HTTP/1.0客户端的日期(尽管目前真正的HTTP/1.0客户端完全不存在)。

额外好处:新的HTTP缓存RFC。


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

在铬(V28.0.1500.95 m)中,我们只能通过Cache-Control: no-store来实现这一点。好的。

在火狐(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-storeHTML格式的好的。

  • 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-revalidateExpires: 0好的。

  • Cache-Control: must-revalidateExpires: Sat, 12 Oct 1991 05:00:00 GMT好的。

  • Pragma: no-cache(仅限https)好的。

  • Vary: *(仅限https)好的。

  • 结合以上内容,我们得到了适用于Chrome28、Firefox 23、IE8、Safari 5.1.7和Opera 12.15的解决方案:Cache-Control: no-store, must-revalidate(仅限https)好的。

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

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

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

    http:好的。

  • Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0Expires: 0Pragma: no-cacheVary: *fail: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=0Expires: Sat, 12 Oct 1991 05:00:00 GMTPragma: no-cacheVary: *fail: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=0Expires: 0Pragma: no-cacheVary: *fail: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=0Expires: Sat, 12 Oct 1991 05:00:00 GMTPragma: no-cacheVary: *fail: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=0Expires: 0Pragma: no-cacheVary: *fail: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=0Expires: Sat, 12 Oct 1991 05:00:00 GMTPragma: no-cacheVary: *fail: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=0Expires: 0Pragma: no-cacheVary: *fail: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=0Expires: Sat, 12 Oct 1991 05:00:00 GMTPragma: no-cacheVary: *fail:chrome 28,firefox 23,safari 5.1.7,opera 12.15成功:IE8好的。

  • Cache-Control: no-storefail:safari 5.1.7,opera 12.15成功:Chrome 28、Firefox 23、IE8好的。

  • Cache-Control: no-storefail:opera 12.15成功:Chrome 28、Firefox 23、IE8、Safari 5.1.7好的。

  • Cache-Control: no-cachefail:chrome 28,firefox 23,safari 5.1.7,opera 12.15成功:IE8好的。

  • Vary: *fail:chrome 28,firefox 23,ie8,safari 5.1.7,opera 12.15成功:无好的。

  • Pragma: no-cachefail: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=0Expires: Sat, 12 Oct 1991 05:00:00 GMTPragma: no-cacheVary: *fail: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=0Expires: 0Pragma: no-cacheVary: *fail:chrome 28,firefox 23,safari 5.1.7,opera 12.15成功:IE8好的。

  • Cache-Control: must-revalidate, max-age=0fail:chrome 28,firefox 23,safari 5.1.7,opera 12.15成功:IE8好的。

  • Cache-Control: must-revalidateExpires: 0fail:chrome 28,firefox 23,safari 5.1.7,opera 12.15成功:IE8好的。

  • Cache-Control: must-revalidateExpires: Sat, 12 Oct 1991 05:00:00 GMTfail:chrome 28,firefox 23,safari 5.1.7,opera 12.15成功:IE8好的。

  • Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0Pragma: no-cacheVary: *fail:chrome 28,firefox 23,ie8,safari 5.1.7,opera 12.15成功:无好的。

  • HTTPS:好的。

  • Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0Expires: 0fail:chrome 28,firefox 23,ie8,safari 5.1.7,opera 12.15成功:无好的。

  • Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0Expires: Sat, 12 Oct 1991 05:00:00 GMTfail:chrome 28,firefox 23,ie8,safari 5.1.7,opera 12.15成功:无好的。

  • Vary: *fail:chrome 28,safari 5.1.7,opera 12.15成功:火狐23,IE8好的。

  • Pragma: no-cachefail:chrome 28,safari 5.1.7,opera 12.15成功:火狐23,IE8好的。

  • Cache-Control: no-cachefail:chrome 28,safari 5.1.7,opera 12.15成功:火狐23,IE8好的。

  • Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0fail:chrome 28,safari 5.1.7,opera 12.15成功:火狐23,IE8好的。

  • Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0Expires: 0Pragma: no-cacheVary: *fail:chrome 28,safari 5.1.7,opera 12.15成功:火狐23,IE8好的。

  • Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0Expires: Sat, 12 Oct 1991 05:00:00 GMTPragma: no-cacheVary: *fail:chrome 28,safari 5.1.7,opera 12.15成功:火狐23,IE8好的。

  • Cache-Control: must-revalidatefail:chrome 28,firefox 23,ie8,safari 5.1.7成功:歌剧12.15好的。

  • Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0fail:chrome 28,firefox 23,ie8,safari 5.1.7成功:歌剧12.15好的。

  • Cache-Control: must-revalidate, max-age=0fail:chrome 28,firefox 23,safari 5.1.7成功:IE8,歌剧12.15好的。

  • Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0Expires: Sat, 12 Oct 1991 05:00:00 GMTPragma: no-cacheVary: *fail:chrome 28,safari 5.1.7成功:火狐23、IE8、Opera 12.15好的。

  • Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0Expires: 0Pragma: no-cacheVary: *fail:chrome 28,safari 5.1.7成功:火狐23、IE8、Opera 12.15好的。

  • Cache-Control: no-storefail: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=0Expires: 0Pragma: no-cacheVary: *fail: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=0Expires: Sat, 12 Oct 1991 05:00:00 GMTPragma: no-cacheVary: *fail:opera 12.15成功:Chrome 28、Firefox 23、IE8、Safari 5.1.7好的。

  • Cache-Control: private, no-cacheExpires: Sat, 12 Oct 1991 05:00:00 GMTPragma: no-cacheVary: *fail:chrome 28,safari 5.1.7,opera 12.15成功:火狐23,IE8好的。

  • Cache-Control: must-revalidateExpires: 0fail:chrome 28,firefox 23,safari 5.1.7,成功:IE8,歌剧12.15好的。

  • Cache-Control: must-revalidateExpires: Sat, 12 Oct 1991 05:00:00 GMTfail:chrome 28,firefox 23,safari 5.1.7,成功:IE8,歌剧12.15好的。

  • Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0Expires: 0fail:chrome 28,firefox 23,safari 5.1.7,成功:IE8,歌剧12.15好的。

  • Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0Expires: Sat, 12 Oct 1991 05:00:00 GMTfail:chrome 28,firefox 23,safari 5.1.7,成功:IE8,歌剧12.15好的。

  • Cache-Control: private, must-revalidateExpires: Sat, 12 Oct 1991 05:00:00 GMTPragma: no-cacheVary: *fail:chrome 28,safari 5.1.7成功:火狐23、IE8、Opera 12.15好的。

  • Cache-Control: no-store, must-revalidatefail:none成功:Chrome 28、Firefox 23、IE8、Safari 5.1.7、Opera 12.15好的。

  • 好啊。


    我发现web.config路由很有用(尝试将其添加到答案中,但似乎未被接受,因此在此处发布)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <configuration>
    <system.webServer>
        <httpProtocol>
            <customHeaders>
               
                <!-- HTTP 1.1. -->
               
                <!-- HTTP 1.0. -->
               
                <!-- Proxies. -->
            </customHeaders>
        </httpProtocol>
    </system.webServer>

    下面是express/node.js的方法:

    1
    2
    3
    4
    5
    6
    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使用该页面的缓存版本。

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

    Cache-Control: no-store
    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直接放在地址栏中时,这些头会导致从服务器请求页面。截至2010年1月,这覆盖了99%的浏览器。

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

    更新:在写下这个答案之后,我意识到我们的Web服务器将自己标识为一个HTTP1.0服务器。我列出的头是正确的,以便浏览器不缓存来自HTTP 1.0服务器的响应。对于HTTP1.1服务器,请查看Balusc的答案。


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

    • 有效期至:1997年7月26日周一05:00:00 GMT
    • 缓存控制:无缓存,私有,必须重新验证,max stale=0,post check=0,pre check=0,无存储
    • pragma:没有缓存

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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


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

    http://www.mnot.net/cache_docs/pragma


    免责声明:我强烈建议阅读@balusc的答案。在阅读了以下缓存教程:http://www.mnot.net/cache_docs/(我建议您也阅读它),我相信它是正确的。但是,出于历史原因(并且因为我自己测试过),我将在下面列出我的原始答案:


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

    1
    2
    3
    4
    5
    6
    7
    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()函数调用中,他必须这样做:

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

    请参阅此处的更多完整文档。


    IE6中有一个错误

    即使使用"cache-control:no-cache",也始终缓存带有"content-encoding:gzip"的内容。

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

    您可以为IE6用户禁用gzip压缩(检查用户代理中的"msie 6")。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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注册

    1
    app.UseMiddleware<NoCacheMiddleware>();

    一定要在后面加上这个

    1
    app.UseStaticFiles();

    HTTP 1.1的RFC表示,正确的方法是为以下对象添加一个HTTP头:

    缓存控制:无缓存

    如果旧的浏览器不符合HTTP1.1,它们可能会忽略这一点。对于那些你可以尝试的标题:

    pragma:没有缓存

    这也应该适用于HTTP 1.1浏览器。


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

    1
    2
    3
    4
    5
    6
    7
        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);

    这些指令不能减轻任何安全风险。它们实际上是为了迫使行动单位更新易变信息,而不是阻止行动单位保留信息。看看这个类似的问题。至少,不能保证任何路由器、代理等也不会忽略缓存指令。

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


    将修改后的HTTP头设置为1995年的某个日期通常可以做到这一点。

    下面是一个例子:

    1
    2
    3
    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


    如果您在SSL和缓存上遇到IE6-IE8下载问题:MS Office文件没有缓存头(和类似的值),则可以使用缓存:private,no store header,以及post请求时返回的文件。它起作用了。


    在我的例子中,我用这个解决了Chrome的问题

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

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


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

    1
    ExpiresDefault"access plus 0 seconds"

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

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

    如果您的动态文件(如php等)被浏览器缓存,并且您无法找出原因,那么这也会很方便。检查ExpiresDefault


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

    1
    <body onunload="">

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


    通过设置pragma:没有缓存


    接受的答案似乎对iis7+不起作用,因为有大量关于ii7中未发送的缓存头的问题:

    • 一些东西迫使响应具有缓存控制:在IIS7中是私有的
    • iis7:缓存设置不工作…为什么?
    • iis7+asp.net MVC客户端缓存头不工作
    • 为ASPX页设置缓存控制
    • 缓存控制:没有存储,必须重新验证没有发送到IIS7+ASP.NET MVC中的客户端浏览器

    等等

    接受的答案是正确的,其中必须设置标题,而不是必须如何设置标题。此方法适用于iis7:

    1
    2
    3
    4
    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


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


    1
    2
    3
    4
    5
    6
    7
    8
    //In .net MVC
    [OutputCache(NoStore = true, Duration = 0, VaryByParam ="*")]
    public ActionResult FareListInfo(long id)
    {
    }

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

    完成balusc->answer如果您使用的是Perl,那么可以使用CGI添加HTTP头。

    使用Perl:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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

    1
    2
    3
    4
    5
    6
    7
    8
    <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元时,浏览器忽略了它们并缓存了页面。


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

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

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

    还有一个警告。小心使用httpResponse类的clearHeaders方法。如果你鲁莽使用它可能会给你一些瘀伤。就像它给我的。

    在actionfilterattribute事件上重定向之后,清除所有头的结果将丢失tempdata存储中的所有会话数据和数据。在执行重定向时,从操作重定向或不清除头更安全。

    第二个想法是,我不鼓励所有人使用ClearHeaders方法。最好单独拆下收割台。为了正确设置缓存控制头,我使用以下代码:

    1
    2
    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不接受其他控制。链接是一个很好的阅读,包括缓存和文档概念证明的历史。


    我对江户十一〔二〕行没什么好运气。直接添加与HTTP缓存相关的参数(在HTML文档之外)确实对我有用。

    下面是使用web.py web.header调用的python中的示例代码。我有目的地修改了与我个人无关的实用程序代码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
        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()

    推荐阅读

      linux安装浏览器命令?

      linux安装浏览器命令?,官网,系统,平台,网站,管理,设备,咨询,工具,官方网站,

      linux命令行远程控制?

      linux命令行远程控制?,系统,地址,服务,网络,电脑,软件,工具,实时,网站,命令,W

      linux清除缓存命令?

      linux清除缓存命令?,系统,工具,情况,缓存,网络,服务,管理,信息,地址,数据,Lin

      linux全程控制命令?

      linux全程控制命令?,地址,工作,命令,基础,系统,网络,管理,目录,控制台,路径,l

      linux命令怎么控制的?

      linux命令怎么控制的?,地址,工作,系统,标准,命令,电脑,基础,管理,灵活,网站,l

      linux控制台停止命令?

      linux控制台停止命令?,地址,工具,平台,网络,下来,电脑,状态,命令,程序,进程,L

      linux查看缓存命令?

      linux查看缓存命令?,系统,地址,网络,信息,第一,情况,命令,电脑,状态,标准,下

      linux浏览网页的命令?

      linux浏览网页的命令?,工作,系统,传播,地址,命令,环境,发行,信息,网络,基础,l

      linux命令访问网页?

      linux命令访问网页?,地址,传播,网络,系统,软件,网址,密码,服务,数据,首次,lin

      linux启动浏览器命令?

      linux启动浏览器命令?,系统,情况,发行,不了,官网,环境,工具,传播,基础,软件,

      刷新缓存linux命令?

      刷新缓存linux命令?,系统,地址,工作,情况,工具,信息,盘中,状态,数据,命令,Lin

      linux网页访问命令?

      linux网页访问命令?,地址,网络,工作,系统,命令,传播,信息,软件,代码,首次,在L

      linux默认浏览器命令?

      linux默认浏览器命令?,环境,系统,发行,工程,工具,浏览器,软件,情况,网站,管

      linux命令下载浏览器?

      linux命令下载浏览器?,软件,系统,官网,网站,工具,名称,中心,密码,时间,设计,l

      linux命令控制声卡?

      linux命令控制声卡?,软件,检测,设备,工作,声卡,官方网站,标准,电脑,情况,位

      linux命令关浏览器?

      linux命令关浏览器?,系统,工作,工具,咨询,信息,平台,官方网站,管理,数据,电

      linux作业控制命令?

      linux作业控制命令?,工作,系统,信息,地址,管理,命令,目录,大地,行业,术语,lin

      linux退出控制台命令?

      linux退出控制台命令?,地址,工作,命令,图片,管理,系统,目录,信息,标准,控制

      linux命令链接网页?

      linux命令链接网页?,网络,信息,系统,网址,工具,网站,状态,发行,数据,命令,Lin

      linux登陆网页命令?

      linux登陆网页命令?,系统,网络,工作,地址,信息,服务,工具,认证,形态,密码,怎