强缓存本身不能防御缓存中毒,反而可能加剧风险——关键在于“如何配置”和“配置给谁”,需精准控制缓存范围、严格约束缓存键、阻断敏感上下文进入公共缓存。

强缓存本身不能防御缓存中毒,反而可能加剧风险——关键在于“如何配置”和“配置给谁”。缓存中毒攻击(如Web缓存投毒)的本质,是攻击者利用缓存系统对请求参数、HTTP头等字段的解析缺陷,将恶意响应注入到被多用户共享的公共缓存中。而强缓存若盲目启用 public, max-age,恰恰会把错误响应长期固化、广泛分发。真正有效的配置策略,是**精准控制缓存范围、严格约束缓存键、阻断敏感上下文进入公共缓存**。
明确缓存层级与作用域:只对静态资源开强缓存
强缓存应仅用于真正无状态、无用户上下文的资源,例如:
- CSS、JS、字体、图标等前端静态文件(版本化命名如
app.a1b2c3.js) - 公开图片、SVG、JSON Schema 等不依赖 Cookie/Session 的内容
- 完全由 CDN 缓存的营销页、帮助文档等只读页面
禁止对以下资源启用 public 强缓存:
- 含用户身份信息的接口(如
/api/profile) - 依赖
Cookie、Authorization或X-User-ID头的动态响应 - 任何 URL 中带用户可控参数(如
?ref=xxx、?utm_source=xxx)且该参数影响响应内容的页面
设置安全的 Cache-Control 响应头
服务端返回时,必须根据资源性质精确设置:
- 静态资源:使用
Cache-Control: public, max-age=31536000, immutable(一年+不可变,防止热更新覆盖) - 需登录但内容通用的资源(如首页 HTML 模板):用
Cache-Control: private, max-age=300(5 分钟私有缓存,仅限当前用户) - 含敏感或个性化数据的接口:强制禁用缓存,设为
Cache-Control: no-store(不存储任何副本) - 若必须支持协商缓存(如部分 HTML),禁用强缓存但保留验证能力:
Cache-Control: no-cache, must-revalidate
注意:public 是高危标识,除非确认响应体完全不包含用户数据、不拼接 Host/Referer/自定义头,否则一律避免使用。
收紧缓存键(Cache Key)设计
缓存中毒常因缓存系统将本该区分的请求视为相同缓存键。需在反向代理(如 Nginx、Varnish)或 CDN 配置中显式声明缓存键维度:
- 默认只包含
method + scheme + host + path + query,不包含Cookie、Authorization、User-Agent等用户特有头 - 若业务逻辑依赖
Accept-Language返回不同文案,必须将其加入缓存键,否则中文用户可能拿到英文缓存 - 绝对禁止将
Host、Origin、Referer等可被攻击者控制的头纳入缓存键——这是缓存投毒最常见入口 - Nginx 示例:
proxy_cache_key "$scheme$request_method$host$request_uri";(不带 $http_x_forwarded_for 等)
配合 WAF 与请求过滤做前置拦截
强缓存配置是结果层防护,源头需阻断恶意请求抵达缓存环节:
- 在 WAF(如华为云 WAF、Cloudflare WAF)中开启 Header 全检测,规则拦截含异常
Host(如 IP 地址、端口号、非法域名)、畸形Referer、可疑查询参数(?callback=alert(1))的请求 - 对所有非静态资源路径(如
/api/、/user/),WAF 可配置为自动添加Cache-Control: no-store响应头,覆盖后端误配 - 在应用网关层(如 API Gateway)统一剥离或校验
Host、X-Forwarded-Host,只允许白名单域名通过
不复杂但容易忽略











