首页 文章

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

提问于
浏览
1289

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

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

  • Internet Explorer 6

  • Firefox 1.5

  • Safari 3

  • 歌剧9

  • Chrome

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

26 回答

  • 2215

    请参阅此链接以获取有关缓存的案例研究:

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

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

  • 23

    在我的情况下,我用铬修复了问题

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

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

  • 6

    除了 Headers 之外,请考虑通过 https 为您的页面提供服务 . 许多浏览器默认不会缓存https .

  • 6

    要完成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>
    

    Note: 当我尝试使用html META时,浏览器会忽略它们并缓存页面 .

  • 4

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

    <body onunload="">
    

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

  • 4

    HTTP 1.1的RFC说适当的方法是为以下内容添加HTTP标头:

    缓存控制:无缓存

    如果较旧的浏览器不正确地符合HTTP 1.1,则可能会忽略它 . 对于那些你可以尝试 Headers :

    Pragma:没有缓存

    这也适用于HTTP 1.1浏览器 .

  • 3

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

    在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

  • 7

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

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

  • 4

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

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

    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()
    
  • 6

    这些指令不会降低任何安全风险 . 它们实际上是为了迫使UA 's to refresh volatile information, not keep UA' s保留信息 . 见this similar question . 至少,不能保证任何路由器,代理等也不会忽略缓存指令 .

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

  • 5

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

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

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

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

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

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

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

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

    简介

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

    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 参数,则其他 Cache-Control 参数(如 max-age )无关紧要 . 这里的大多数其他答案中包含的Last-Modified Headers 仅在您缓存请求时才有意义,因此您根本不需要指定它 .

    如何设置?

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

    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 / 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页面通过HTTP连接提供,并且HTTP响应头和HTML <meta http-equiv> 标签中存在标头时,HTTP响应头中指定的标头将优先于HTML元标记 . 仅当通过 file:// URL从本地磁盘文件系统查看页面时,才会使用HTML元标记 . 另见W3 HTML spec chapter 5.2.2 . 如果不以编程方式指定它们,请注意这一点,因为Web服务器可以包含一些默认值 .

    通常,您最好只是 not 指定HTML元标记以避免启动者混淆,并依赖于硬HTTP响应标头 . 此外,特别是那些 <meta http-equiv> 标签在HTML5中是invalid . 仅允许HTML5 specification中列出的 http-equiv 值 .

    验证实际的HTTP响应标头

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

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

    我想在文件下载上设置这些 Headers

    首先,这个问题和答案的目标是"web pages"(HTML页面),而不是"file downloads"(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 .

  • 213

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

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

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

    有关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时,这些 Headers 会导致从服务器请求页面直接在地址栏中 . 这涵盖了截至2010年1月所使用的所有浏览器中的_235340 .

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

    Update: 写完这个答案之后,我意识到我们的Web服务器将自己标识为HTTP 1.0服务器 . Headers 我've listed are the correct ones in order for responses from an HTTP 1.0 server to not be cached by browsers. For an HTTP 1.1 server, look at BalusC' s answer .

  • 4

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

  • 0

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

    ExpiresDefault "access plus 0 seconds"
    

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

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

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

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

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

    IE6中有一个错误

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

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

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

  • 7

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

  • 3

    将修改后的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
    
  • 6

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

    这应该工作 . 问题是当设置 Headers 的相同部分两次时,如果 false 未作为第二个参数发送到 Headers 函数,则 Headers 函数将简单地覆盖之前的 header() 调用 . 因此,在设置 Cache-Control 时,例如,如果不希望将所有参数放在一个 header() 函数调用中,他必须执行以下操作:

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

    查看更完整的文档here .

  • 18

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

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

    Combining the above gives us this solution which works for Chrome 28, FireFox 23, IE8, Safari 5.1.7, and 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="">
      失败:歌剧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="">
      失败:歌剧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="">
      失败:歌剧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,Safari5.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
      失败:歌剧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="">
      失败:歌剧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="">
      失败:歌剧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

  • 87

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

    等等

    接受的答案是正确的,必须设置哪个 Headers ,而不是必须如何设置 Headers . 这种方式适用于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

  • 8

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

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

    首先,Back button history is not a cache

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

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

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

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

    • 页面必须通过 HTTPS 递送,否则此缓存破坏赢得了't be reliable. Plus, if you'不使用HTTPS,那么您的页面很容易在许多其他方式登录窃取 .

    • 你必须发送 Cache-Control: no-store, must-revalidate (某些浏览器观察 no-store ,有些浏览器观察 must-revalidate

    你永远不需要任何:

    带有缓存标头的

    • <meta> - 根本不起作用 . 完全没用 .

    • post-check / pre-check - 它是仅适用于可缓存资源的IE-only指令 .

    • 两次或十几个部分发送相同的 Headers . 一些PHP片段实际上取代了以前的 Headers ,导致只发送了最后一个 .

    如果需要,可以添加:

    • no-cachemax-age=0 ,这将使资源(URL)"stale"并要求浏览器检查服务器是否有更新的版本( no-store 已经暗示这更强大) .

    • Expires ,其中包含HTTP / 1.0客户端的过去日期(尽管这些天真正的HTTP / 1.0仅客户端完全不存在) .


    额外奖励:The new HTTP caching RFC .

相关问题