强制缓存的核心是用proxy_ignore_headers屏蔽后端禁止缓存头,使Nginx自主决策;必须忽略Cache-Control、Expires、Set-Cookie、Vary等头,并严格校验安全性与场景适用性。

直接用 proxy_ignore_headers 屏蔽后端返回的禁止缓存头,再由 Nginx 自主决定缓存行为——这是强制缓存“不支持缓存”资源的核心逻辑。关键不是让后端变支持,而是让 Nginx 不听它的。
哪些头必须忽略才能强制缓存
后端常通过以下响应头表达“不准缓存”,Nginx 默认会严格遵守;要强制缓存,就得显式忽略它们:
-
Cache-Control:尤其当值为
no-cache、no-store、private或max-age=0时,Nginx 默认跳过缓存;忽略后,它就只认你写的proxy_cache_valid -
Expires:若后端设了过期时间早于当前时间(如
Expires: 1970-01-01),Nginx 视为不可缓存;忽略后,该头不再参与判断 - Set-Cookie:Nginx 默认拒绝缓存任何含此头的响应(防 session 泄露);忽略它可解锁缓存,但仅限内容完全无状态的场景(如未登录首页带跟踪 Cookie)
-
Vary:虽不直接禁缓存,但会让同一 URL 生成多个缓存副本(如按
User-Agent分离),造成碎片;忽略后统一缓存一份,节省空间
典型配置写法(以静态资源为例)
假设后端 Node.js 或 PHP 对所有 .js、.css 响应都加了 Cache-Control: no-cache,但你知道这些是构建产物、带哈希、长期不变:
location ~* \.(js|css|png|jpg|woff2?)$ {
proxy_pass http://origin;
proxy_ignore_headers Cache-Control Expires Set-Cookie;
proxy_cache_valid 200 302 1h;
proxy_cache my_cache;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cache-Status $upstream_cache_status;
}
注意:proxy_ignore_headers 必须写在 proxy_pass 之后、proxy_cache 相关指令之前;多个头用空格分隔,不能换行或加逗号。
安全与可用性必须检查的点
强制缓存不是无代价的,这几项不确认清楚,容易出问题:
- 忽略
Cache-Control后,no-store和private失效——如果后端响应实际含敏感字段(如用户手机号、token),它可能被写入共享缓存区,务必提前审计响应体 - 忽略
Set-Cookie前,确保响应里没有sessionid、CSRF-Token等上下文信息;建议同步加proxy_hide_header Set-Cookie,防止客户端收到错误 Cookie - 若目标是给 CDN 提供稳定缓存源,可在忽略后用
add_header Cache-Control "public, max-age=3600" always;主动注入 CDN 友好头,不依赖后端 - 验证是否生效:用
curl -I查看响应头中是否仍有no-cache,再查X-Cache-Status是否出现HIT;浏览器 Network 面板看资源是否显示from memory cache
不推荐直接忽略的场景
有些情况即使加了 proxy_ignore_headers,也不该强制缓存:
- 用户登录态页面(如
/user/profile)返回了Set-Cookie+ 个性化内容——忽略后缓存会污染,不同用户看到彼此数据 - API 接口返回
Cache-Control: private, max-age=60,且响应体含用户 ID 字段——这属于明确的私有缓存意图,不应覆盖 - 后端通过
Vary: Cookie区分会员/非会员内容——忽略Vary会导致非会员看到会员页,或反之











