nginx 缓存因 set-cookie 被默认跳过,需用 proxy_ignore_headers set-cookie 让缓存决策忽略该头,并配 proxy_hide_header set-cookie 阻止透传,仅当响应无敏感数据且无禁用缓存指令时才可安全启用。

缓存绕过本身不是问题,但当它导致客户端收到错误的 Set-Cookie(比如旧 Token、空值、跨用户 Cookie),说明缓存策略与响应头逻辑存在错配。这类问题隐蔽性强,常表现为“偶发登录态错乱”“A 用户看到 B 用户的数据”或“登出后仍能访问私有接口”。排查需聚焦三点:Nginx 是否本该缓存却绕过了、是否不该缓存却误缓存了、以及缓存内容是否被污染。
确认是否真发生了缓存绕过
先排除“根本没走缓存”的假象:
- 检查响应头中是否有 X-Cache-Status: BYPASS 或 X-Cache-Status: MISS(取决于你自定义的 header);没有该字段,说明压根没启用缓存
- 用 curl -v http://your-api/ 2>&1 | grep 'X-Cache' 看实际返回,对比两次请求——若始终是 MISS,说明 location 块未命中,或 proxy_pass 指向了错误 upstream
- 确认请求 URL 是否带动态参数(如 ?t=123456)、请求头是否含 Cache-Control: no-cache 或 Pragma: no-cache,这些会直接触发 Nginx 跳过缓存
定位错误 Set-Cookie 的来源
不是所有 Set-Cookie 都该被缓存,关键看它是否随响应体“绑定”了用户上下文:
- 抓包比对:用 curl -sI http://your-api/login 和 curl -sI http://your-api/config 分别查看原始上游响应。如果 /login 返回了含 session_id 的 Set-Cookie,而 /config 也返回了同名 Cookie(但值固定),那后者才适合缓存
- 检查后端是否“误设”:有些框架(如 Spring Security)在未登录时仍返回 Set-Cookie: JSESSIONID=xxx; Path=/,这个 ID 实际无效,但会被缓存并透传给下一个用户
- 验证缓存键:Nginx 默认用 $scheme$host$request_uri 作 key。若后端通过 Header(如 X-User-ID)动态生成 Cookie,但没在 proxy_cache_key 中包含该 Header,则不同用户会共享同一缓存条目,导致 Set-Cookie 错乱
检查 proxy_ignore_headers 是否被误用
这是最常见诱因:加了 proxy_ignore_headers Set-Cookie,却没配 proxy_hide_header Set-Cookie:
- 前者只让 Nginx 在“决定缓不缓存”时忽略该头,但缓存下来的响应体里依然带着原始 Set-Cookie
- 后者才是阻止它发给客户端的关键。漏掉这行,缓存命中时,浏览器就会收到上次请求留下的 Cookie,造成污染
- 注意大小写:必须写 Set-Cookie,写成 set-cookie 或 cookie 无效
验证缓存内容是否干净
绕过问题最终要落到“缓存里存了什么”:
- 进入 Nginx 缓存目录(如 /var/cache/nginx/my_cache/),找一个对应 URL 的缓存文件,用 strings xxx | grep -i 'set-cookie' 查看其原始内容。若发现非空、非固定值的 Cookie,说明上游本就不该返回它
- 临时禁用缓存(注释掉 proxy_cache 相关行),用 curl 对比开启/关闭时的 Set-Cookie 是否一致。若关闭后正常、开启后异常,基本锁定是缓存污染
- 检查是否启用了 proxy_cache_use_stale updating:该配置会让 Nginx 在后台更新缓存时,继续返回旧内容。若旧缓存里存着过期 Cookie,就可能被持续下发











