no-store 是唯一能确保敏感路径接口绝不缓存的指令,需精确匹配路径、用 always 参数覆盖上游头、补全 Pragma 和 Expires 兼容头,并验证响应头无冗余。

要让机密路径接口(比如 /api/payment/submit、/auth/logout、含敏感令牌的回调地址)在浏览器、CDN、代理甚至 Service Worker 中完全不留下任何缓存副本,no-store 是唯一能达成“绝不占用终端缓存”目标的指令。它不是“不走缓存”,而是“禁止保存任何字节”,比 no-cache 更彻底。
明确匹配敏感路径并强制注入 no-store
不能依赖全局配置或模糊正则,必须精准定位路径。例如:
- 用精确匹配处理登出接口:
location = /auth/logout { add_header Cache-Control "no-store, no-cache, must-revalidate" always; } - 用前缀匹配覆盖所有支付提交路径:
location ^~ /api/payment/ { add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0" always; } - 对带令牌的回调(如 OAuth 授权完成页)也单独声明:
location ~* /callback\?token= { add_header Cache-Control "no-store" always; }
绕过上游服务干扰,确保 no-store 生效
如果后端(如 Node.js 或 PHP)已返回自己的 Cache-Control,Nginx 默认不会覆盖——你写的 add_header 可能被忽略或与上游头共存,而浏览器只认第一个。必须用以下任一方式破除干扰:
- 加
always参数(Nginx ≥ 1.7.5):它让 Nginx 在所有状态码下都输出该头,并抑制同名上游头的实际发送 - 配合
proxy_hide_header Cache-Control(反向代理场景):先隐藏后端头,再用add_header注入干净的no-store - 避免混用
expires指令:它会自动生成Cache-Control,可能与你的no-store冲突,直接删掉或设为expires epoch;
补全兼容性头,堵住老旧客户端漏洞
no-store 是 HTTP/1.1 标准指令,但部分旧版 IE 或中间代理仍依赖 HTTP/1.0 的 Pragma 头。单靠 Cache-Control 不够稳妥:
- 添加
add_header Pragma "no-cache" always;—— 虽然语义上no-cache≠no-store,但 IE 会将其解释为“禁止存盘”,实际效果接近 - 设置
add_header Expires "Fri, 01 Jan 1990 00:00:00 GMT" always;或expires epoch;,让过期时间绝对无效 - 不要加
public、private或immutable等修饰词——它们与no-store逻辑冲突,可能引发解析歧义
验证是否真正生效
上线后务必用真实请求验证,不能只看 Nginx 配置是否加载:
- 用
curl -I https://yoursite.com/auth/logout检查响应头是否只有一组Cache-Control: no-store...,且无重复或残留的上游头 - 在 Chrome DevTools → Network → Headers 中查看 Response Headers,确认
Cache-Control、Pragma、Expires全部存在且值符合预期 - 触发一次请求后,清空浏览器缓存,再刷新页面并观察是否仍发出完整 GET 请求(而非 304),同时检查 Application → Cache Storage 和 Service Workers 是否未写入任何 entry


















