为什么在 HTTP 响应中同时使用无缓存和无存储?

我被告知要防止用户信息泄露,只有“无缓存”的响应是不够的。“无存储”也是必要的。

Cache-Control: no-cache, no-store

在阅读了这个规范 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html之后,我仍然不太确定为什么。

我目前的理解是,它只适用于中间缓存服务器。即使响应为“ no-cache”,中间缓存服务器仍然可以将内容保存到非易失性存储器。中间缓存服务器将决定是否将保存的内容用于以下请求。但是,如果响应中包含“ no-store”,则中间缓存服务器不应该存储内容。所以,这样更安全。

还有什么其他原因让我们同时需要“无缓存”和“无存储”吗?

181271 次浏览

在某些情况下,即使 Cache-Control: no-cache在响应头中,IE6仍然会缓存文件。

返回文章页面 W3C 状态的 no-cache:

如果 no-cache 指令没有 指定字段名,然后是缓存 不能使用响应来满足 其后的要求不成功 与原始服务器重新验证。

在我的应用程序中,如果你访问一个带有 no-cache头的页面,然后登出,然后在浏览器中回击,IE6仍然会从缓存中抓取该页面(没有向服务器发出新的/验证请求)。添加 no-store头部阻止了它这样做。但是如果你相信 W3C 的话,实际上是没有办法控制这种行为的:

历史缓冲区可能存储这样的响应作为其正常操作的一部分。

描述了浏览器历史记录和普通 HTTP 缓存之间的一般差异。

来自 HTTP 1.1规范:

没有商店 :

没有商店指令的目的是防止无意中释放或保留敏感信息(例如,在备份磁带上)。No-store 指令适用于整个消息,可以在响应或请求中发送。如果在请求中发送,缓存必须不存储此请求的任何部分或对其的任何响应。如果在响应中发送,缓存必须不存储此响应或引发此响应的请求的任何部分。此指令同时适用于非共享缓存和共享缓存。“必须不存储”在这种情况下意味着缓存必须不故意存储在非易失性存储的信息,必须尽最大努力删除信息从挥发性记忆体转发后,尽可能迅速。 即使该指令与响应相关联,用户也可以在缓存系统之外显式地存储这样的响应(例如,使用“另存为”对话框)。历史缓冲区可能存储这样的响应作为其正常操作的一部分。 本指令的目的是满足某些用户和服务提供者的明确要求,这些用户和服务提供者担心通过意外访问缓存数据结构意外发布信息。虽然这个指令的使用可能会在某些情况下改善隐私,但我们警告说,它不是一个可靠的或充分的机制,以确保隐私。特别是,恶意缓存或受损缓存可能无法识别或遵守此指令,通信网络可能容易被窃听。

最初我们在很多年前使用了 no-cache,并且在某些浏览器上遇到了一些陈旧内容的问题... ... 不幸的是,我们不记得具体细节了。

从那以后,我们决定只使用没有商店的方式。从来没有回头看或有任何过时的内容的问题,由任何浏览器或中介。

这个空间当然是由实现的实际情况和在各种 RFC 中编写的内容所主导的。许多代理人尤其倾向于认为,他们通过用自己的政策取代他们应该遵循的政策,在“改善性能”方面做得更好。

no-store在正常情况下不应该是必需的,并且会损害速度和可用性。它用于 HTTP 响应所包含的信息如此敏感,以至于根本不应该写到磁盘缓存中,不管对用户造成什么负面影响。

工作原理:

  • 通常,即使用户代理(如浏览器)确定不应该缓存响应,由于用户代理内部的原因,它仍然可以将响应存储到磁盘缓存中。这个版本可以用于“查看源代码”、“返回”、“页面信息”等功能,在这些功能中,用户没有必要再次请求页面,但浏览器并不认为这是一个新的页面查看,因此服务于用户当前正在查看的相同版本是有意义的。

  • 使用 no-store会阻止响应被存储,但是这可能会影响浏览器提供“查看源代码”、“返回”、“页面信息”等等的能力,而不会对服务器发出新的、单独的请求,这是不可取的。换句话说,用户可能会尝试查看源代码,如果浏览器没有将其保存在内存中,他们要么会被告知这是不可能的,要么会向服务器发出新的请求。因此,只有当这些功能不能正常或快速工作的阻碍用户体验被确保内容不存储在缓存中的重要性所超过时,才应该使用 no-store

我目前的理解是,它只适用于中间缓存服务器。即使响应为“ no-cache”,中间缓存服务器仍然可以将内容保存到非易失性存储器。

这是错误的。与 HTTP 1.1兼容的中间缓存服务器将遵守 no-cachemust-revalidate指令,确保内容不被缓存。使用这些指令将确保响应不会被任何中间缓存缓存,并且所有后续请求都会发送回原始服务器。

如果中间缓存服务器不支持 HTTP 1.1,那么您将需要使用 Pragma: no-cache,并希望最好的结果。注意,如果它不支持 HTTP 1.1,那么 no-store无论如何都是不相关的。

如果你想阻止所有的缓存(例如使用后退按钮时强制重新加载) ,你需要:

  • IE 无缓存

  • 火狐没有商店

这是我的信息:

Http://blog.httpwatch.com/2008/10/15/two-important-differences-between-firefox-and-ie-caching/

更糟糕的是,在某些情况下,no-cache 不能使用,但 no-store 可以:

Http://faindu.wordpress.com/2008/04/18/ie7-ssl-xml-flex-error-2032-stream-error/

如果缓存系统正确地实现了无存储,那么您就不需要无缓存。但不是所有人都这样。此外,一些浏览器实现无缓存就像它是无存储。因此,虽然不是严格要求,但最安全的做法可能是同时包含两者。

我必须澄清,no-cache并不意味着 不缓存。实际上,它的意思是在每次请求时,在使用任何缓存响应之前“使用服务器重新验证”。

另一方面,must-revalidate只需要在资源被认为过期时重新验证。

如果服务器说资源仍然有效,那么缓存可以用它的表示来响应,从而减轻服务器重新发送整个资源的需要。

no-store实际上是完整的 不缓存指令,旨在防止以任何形式的缓存存储表示。

我说无论如何,但是请注意 RFC 2616 HTTP 规范中的这一点:

历史缓冲区可能存储这样的响应作为其正常操作的一部分

但是新的 RFC 7234 HTTP 规范忽略了这一点,这可能是为了使 no-store更强大,参见:

Https://www.rfc-editor.org/rfc/rfc7234#section-5.2.1.5

请注意,从版本5到版本8的 Internet Explorer 在尝试下载通过 https 服务的文件时会抛出一个错误,服务器会发送 Cache-Control: no-cachePragma: no-cache头文件。

参见 http://support.microsoft.com/kb/812935/en-us

使用 Cache-Control: no-storePragma: private似乎是最接近的事情,仍然工作。

对于 chrome 来说,no-cache 用于在重新访问时重新加载页面,但是如果你回到历史记录(返回按钮) ,它仍然会缓存页面。要重新加载用于历史回溯的页面,也可以使用 no-store。IE 必须重新验证才能在任何情况下工作。

所以,为了确保避免所有我经常使用的错误和误解

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

如果我想确保它重新装弹的话。

OWASP 讨论了这个问题:

缓存控制指令: no-cache 和 no-store 之间的区别是什么?

响应中的 no-cache 指令表明响应不能用于服务后续请求,即缓存不能显示在头中设置了此指令但必须让服务器服务请求的响应。No-cache 指令可以包含一些字段名; 在这种情况下,可以从缓存中显示响应,但应该从服务器提供的指定字段名除外。No-store 指令应用于整个消息,并指示缓存不能存储响应的任何部分或要求存储响应的任何请求。

这些指令对我来说完全安全吗?

没有。但是一般来说,除了 Exires: 0(或充分回溯的 GMT 日期,比如 UNIX 时代)之外,还可以同时使用 Cache-Control: no-cache、 no-store 和 Pragma: no-cache。即使设置了上述缓存控制指令,非 html 内容类型(如 pdf、 word 文档、 excel 电子表格等)通常也会被缓存(尽管这种情况因版本和必须重新验证、 pre-check = 0、 post-check = 0、 max-age = 0和 s-maxage = 0的额外使用而有所不同,在实践中,由于浏览器的异常和 HTTP 实现,有时至少会导致浏览器关闭时的文件删除)。此外,“自动完成”功能允许浏览器缓存任何用户在表单的输入字段中键入的内容。为了检查这一点,表单标记或单个输入标记应该包含‘ Autocomplete = “ Off”属性。但是,应该注意的是,这个属性是非标准的(尽管主流浏览器支持它) ,因此它会破坏 XHTML 验证。

来源 给你

要回答这个问题,这里有两个参与者,客户机(请求)和服务器(响应)。

客户:

客户端只能请求一个缓存方法。有不同的方法,如果没有指定,将使用 default

  • 默认 : 检查浏览器缓存:
    1. 如果缓存和“新鲜”: 从缓存返回。
    2. 如果缓存过期,但仍然是“有效的”: 从缓存返回,并安排获取更新缓存(供下一次使用)。
    3. 如果缓存过期: 使用条件获取、缓存和返回。
    4. 如果没有缓存: 获取、缓存和返回。
  • No-store : 获取并返回。
  • 重新加载 : 获取、缓存和返回
  • No-cache : 检查浏览器缓存:
    1. 如果缓存: 带条件获取、缓存和返回。(Default-3默认值 -3)
    2. 如果没有缓存: 获取、缓存和返回。(Default-4默认值为4)
  • 强力缓存 : 检查浏览器缓存:
    1. 如果缓存: 返回它,不管它是否过期。
    2. 如果没有缓存: 获取、缓存和返回。(Default-4默认值为4)
  • Only-if-cached : 检查浏览器缓存:
    1. 如果缓存: 返回它,不管它是否过期。
    2. 如果没有缓存: 抛出网络错误。

备注:

  • 仍然“有效”意味着当前的 agestale-while-revalidate生命周期内。它需要“重新验证”,但仍然可以返回。
  • 为了简单起见,这里的“获取”是“无条件网络”的缩写 捡回来”。
  • “使用条件获取”意味着使用如下标题获取 If-Modified-Since,或者 ETag,因此服务器可以用 304: (Not Modified)进行响应。

Https://fetch.spec.whatwg.org/#concept-request-cache-mode

服务器: :

现在我们了解了客户机可以做什么,服务器响应就更有意义了。 查看 Cache-Control头,如果服务器返回:

  • No-store : 告诉客户端根本不要使用缓存
  • No-cache : 告诉客户机它应该执行条件请求并忽略新鲜度
  • Max-age : 告诉客户端缓存“新鲜”的时间
  • Stale-while-revalid : 告诉客户端缓存的有效时间
  • 不可变 : Cache forever

现在我们可以把它们放在一起,这意味着唯一的可能性是:

  • 无条件网络提取
  • 有条件的网络获取
  • 返回过期缓存
  • 返回陈旧但有效的缓存
  • 返回新缓存
  • 返回任何缓存

客户机或服务器的任何组合都可以指定要使用的方法或方法集。如果服务器返回 no-store,则不管客户机请求类型如何,它都不会访问缓存。如果客户机请求是 no-store,那么服务器返回什么并不重要,它不会缓存。如果客户机没有指定请求类型,服务器将使用 Cache-Control对其进行指示。

no-store覆盖了一切开始,服务器同时返回 no-cacheno-store是没有意义的。是的,你可能已经看到两者在一起,它是无用的外部破碎的浏览器实现。尽管如此,no-store自1999年以来一直是规格的一部分: https://datatracker.ietf.org/doc/html/rfc2616#section-14.9.2

在实际使用中,如果您的服务器支持 304: Not Modified,并且您希望使用客户端缓存作为提高速度的方法,但仍然希望强制进行网络提取,则使用 no-cache。如果不支持 304,并希望强制执行网络获取,请使用 no-store。如果有时使用缓存没有问题,那么可以使用新鲜度和重新验证标头。

实际上,如果您在客户机上混淆了 no-cacheno-store,那么几乎不会有什么变化。然后,只有一对夫妇的头被发送,将有不同的内部响应处理的浏览器。如果您使用 no-cache,然后忘记以后使用它,就可能出现问题。no-cache告诉它将响应存储在缓存中,以后没有响应的请求可能会触发内部缓存。

有时候,您可能希望根据上下文在同一资源上混合使用方法。例如,您可能希望在服务工作者和后台同步上使用 reload,但是对网页本身使用 default。在这里,您可以按照自己的喜好操作用户代理(浏览器)缓存。请记住,服务器通常对缓存的工作方式有最终决定权。


为了澄清未来可能出现的混乱。客户可以使用 请求上的 Cache-Control头,告诉服务器在响应时不要使用自己的缓存系统。这与浏览器/服务器动态无关,更多的是关于服务器/数据库动态。

另外,从技术上讲,no-store意味着不能存储到任何非易失性存储(磁盘) ,并尽快从挥发性记忆体(内存)释放它。实际上,这意味着根本不使用缓存。命令实际上是双向的。使用 no-store的客户端请求不应该写到磁盘或数据库,而应该是暂时的。


DR: no-store覆盖 no-cache。除非我们讨论的浏览器不支持 no-store(也许是 IE11?) ,否则设置两者都是无用的.使用 no-cache支持 304

这是一个相当老的话题,但我会分享一些最近的想法:

不能试图存储任何东西,还必须采取措施删除它可能拥有的任何副本。

no-cache: 未经原始服务器验证,不要使用本地副本。它可以防止缓存命中的所有可能性,即使使用新的资源也是如此。

所以,回答这个问题,只使用其中的一个就足够了。 此外,一些(不是很) 最近的作品证明浏览器现在更兼容 Cache-Control。