理解 Cache-Control 头部:公共和个性化响应
本文解释了 HTTP Cache-Control 头部指令 ‘no-store’、‘no-cache’ 和 ‘private’ 的区别,详细说明了它们如何控制公共和个性化响应的缓存行为,并探讨了浏览器诊断和常见陷阱。
本文内容
简明答案
Cache-Control 头部是管理 Web 浏览器和中间缓存(如 CDN)如何处理 Web 资源的至关重要的机制。这些头部指示缓存是否应该存储、验证或阻止存储响应。让我们分解这三个关键指令:‘no-store’、‘no-cache’ 和 ‘private’。‘no-store’ 是最严格的指令。它禁止 *任何* 缓存,包括私有缓存。这对于高度敏感的数据或一次性响应至关重要。示例:Cache-Control: no-store。‘no-cache’ 允许缓存,但强制缓存始终必须与源服务器重新验证响应,然后再使用它。这确保浏览器接收到最新的版本,即使缓存拥有过时的副本。示例:Cache-Control: no-cache。‘private’ 限制缓存仅限于私有缓存 - - 与特定用户关联的缓存,例如浏览器的本地缓存。这可以防止共享缓存向其他用户提供个性化内容。示例:Cache-Control: private。处理个性化响应时,‘private’ 至关重要。例如,用户登录网站时,他们的响应应仅存储在他们的浏览器中,而不是共享 CDN。如果响应包含个性化数据,则使用‘private’至关重要,以防止泄露信息。MDN 文档指出,‘no-cache’ 不意味着“不要缓存”,而是意味着“在重用之前始终验证”。‘no-cache’ 指令并不能保证历史导航会进行验证。此外,‘max-age’ 指令指定响应被认为是新鲜的时长。值为 0 表示响应应始终重新验证。‘immutable’ 指令阻止缓存,即使 max-age 设置为 0,以确保浏览器始终请求资源的最新版本。当检查浏览器的请求头时,您将看到 Cache-Control 指令会影响缓存行为。例如,对于公共资产的请求,您可能会看到 Cache-Control: public max-age=3600,这表示它可以被缓存一个小时。对于私有个人资料的请求,您可能会看到 Cache-Control: private no-cache,以确保仅用户的浏览器可以存储它,并在重用之前需要验证。浏览器诊断可以揭示响应是否被缓存以及如何缓存。例如,浏览器的开发者工具允许您监视网络请求并检查 Cache-Control 头部。常见的错误包括忘记为个性化响应设置 ‘private’,这可能导致数据泄露。另一个错误是仅仅依赖 ‘no-store’,而没有使用更细粒度的方法 - - 有时允许使用验证的缓存是更可取的。决策标准应基于数据的敏感性和所需的缓存行为。最后,请记住,Cache-Control 不是授权边界;‘no-cache’ 不意味着 ‘no storage’。范围限制由使用的特定头部和浏览器和中间缓存实施的缓存策略决定。
区分存储和重用
缓存是一种改善 Web 性能的基本技术,但了解它如何与数据敏感性交互至关重要。核心概念是区分存储响应和重用存储的响应。缓存可以存储响应,但必须在重用之前验证它。‘no-store’ 阻止存储和重用,确保响应永远不会离开客户端的浏览器。‘no-cache’ 允许存储,但强制在重用之前验证,从而确保浏览器始终接收到最新的版本。‘private’ 限制存储仅限于私有缓存,从而防止共享缓存向其他用户提供个性化内容。
考虑一个场景,用户登录。包含他们个性化资料数据的响应应被视为私有。如果没有 ‘private’,共享缓存可能会向其他用户提供此数据,从而危及他们的隐私。MDN 文档强调,‘no-cache’ 不意味着“不要缓存”,而是意味着“在重用之前始终验证。”
理解 no-store
Cache-Control: no-store 指令是最严格的指令。它指示所有缓存 - - 包括私有和共享缓存 - - *不要* 存储响应。这对于高度敏感的数据、一次性响应或永远不应该被重用的内容来说是合适的选择。它有效地禁用了指定资源的缓存。示例:Cache-Control: no-store 将阻止任何缓存存储响应,无论它是否为浏览器缓存或 CDN 缓存。这对于防止未经授权访问敏感信息至关重要。
理解 no-cache
Cache-Control: no-cache 指令允许缓存,但它*始终* 要求缓存在重用之前与源服务器重新验证响应。这确保浏览器接收到资源的最新版本,即使缓存拥有过时的副本。这在性能和数据新鲜度之间取得了平衡。
这个指令并不意味着“不要缓存”,而是意味着“在重用之前始终验证”。浏览器始终会向服务器发出请求来验证缓存副本是否仍然有效。这对于可能经常更改的资源特别有用,例如动态内容。
理解 private
Cache-Control: private 指令限制缓存仅限于私有缓存 - - 与特定用户关联的缓存,例如浏览器的本地缓存。这可以防止共享缓存向其他用户提供个性化内容。这对于保护用户隐私至关重要。
当响应包含个性化数据时,使用 ‘private’ 至关重要。如果没有它,共享缓存可能会向多个用户提供相同的响应,从而可能泄露他们的个人信息。MDN 文档指出,‘private’ 对于接收登录后响应的响应尤其重要。
比较三种响应策略
以下表格总结了这三个指令的关键差异:
| 指令 | 存储 | 验证 | 范围 |
| --------- | ------- | ---------- | ----------- |
| no-store | 否 | N/A | 所有缓存 |
| no-cache | 是 | 总是 | 所有缓存 |
| private | 是 | 总是 | 私有缓存 |
检查浏览器请求
使用浏览器的开发者工具(通常通过按 F12 访问),您可以检查网络请求的 Cache-Control 头部。在“网络”选项卡中查找“头”部分。这将显示浏览器发送的精确头,包括 Cache-Control 指令。
例如,如果您正在查看带有个性化资料的页面,您应该在请求头中看到 Cache-Control: private no-cache。这表明浏览器正在请求将响应仅存储在本地缓存中,并在重用之前需要验证。
处理个性化响应
个性化响应 - - 包含用户特定数据,例如登录信息、偏好或购物车的响应 - - 需要仔细考虑 Cache-Control 头部。始终使用 Cache-Control: private 以防止共享缓存向其他用户提供此数据。
未能做到这一点可能导致严重的隐私泄露和安全漏洞。MDN 文档明确建议为用户个性化内容使用 ‘private’。
认识到排挤和遗留限制
重要的是要认识到,即使使用 ‘no-cache’,浏览器的历史记录缓存(bfcache)也可能在不验证的情况下提供缓存响应。这是一个遗留行为,旨在恢复以前的会话,不受 Cache-Control 头部控制。此外,HTTP/1.0 缓存可能无法完全支持 ‘no-cache’ 指令,从而导致过时的响应被重用。使用 ‘max-age=0, must-revalidate’ 作为解决方法可以解决此问题,但最好使用 ‘no-cache’ 只要可能。
检查清单
- 缓存行为取决于请求/响应和中间件。
- Cache-Control 不是授权边界;no-cache 不意味着 no storage。
- ‘private’ 指令阻止共享缓存提供个性化内容。
- ‘no-store’ 指令阻止所有缓存。
- ‘no-cache’ 指令强制在重用之前验证。
- 可以使用浏览器的开发者工具检查 Cache-Control 头部。
- 理解私有和共享缓存之间的区别至关重要。
- 遗留缓存行为(bfcache)可能绕过 Cache-Control 指令。
- HTTP/1.0 缓存可能无法完全支持 ‘no-cache’。
适用范围
这些头部提供了一种控制缓存行为的机制,但不能保证完全防止缓存或信息泄露。浏览器实现和中间缓存可能表现出不同的行为,并且用户可以覆盖缓存设置。此外,‘no-cache’ 指令不能防止浏览器的历史记录缓存提供过时的响应。