关键是要让缓存键忽略签名参数(如sign、ts),同时透传给后端校验:在http块用map剥离签名参数生成$clean_args,proxy_cache_key设为"$scheme$request_method$host$uri$is_args$clean_args",并配proxy_cache_valid 200 2m与proxy_cache_use_stale updating error timeout http_500。

要让 Nginx 的 proxy_cache 正常缓存带自定义签名校验(如 ?sign=xxx&ts=1733742960)的 URL,关键不是“去掉签名”,而是**让缓存键忽略签名参数,同时确保签名校验逻辑仍由后端执行**。否则缓存会把每个不同签名的请求当成独立资源,完全失去复用价值。
跳过签名参数生成缓存 key
默认 proxy_cache_key 包含完整 $request_uri,签名参数会导致相同资源被重复缓存。需手动构造不带签名的 key:
- 用
$uri+$is_args+$args拆解参数,再用map过滤掉签名字段 - 推荐做法:在
http块中定义 map 变量,剥离常见签名参数
map $args $clean_args {
~^(.*&)?(sign|ts|nonce|sig)=[^&]*(?:&(.*)|$) $1$3;
~^(.*&)?(sign|ts|nonce|sig)=[^&]*$ "";
default $args;
}
proxy_cache_key "$scheme$request_method$host$uri$is_args$clean_args";
这样 /api/data?name=a&sign=abc&ts=123 和 /api/data?name=a&sign=xyz&ts=456 会生成相同的缓存 key。
确保签名校验不被缓存干扰
签名通常用于防篡改或时效性控制,必须由后端验证。Nginx 缓存层不能绕过它,也不能因缓存而跳过验证:
- 不要设置
proxy_ignore_headers Cache-Control或Expires,除非你明确知道后端返回了合理缓存头 - 避免用
proxy_cache_bypass或proxy_no_cache错误地拦截签名请求——它们应只用于调试或管理类参数(如?nocache=1) - 若后端依赖签名参数做权限判断,确保这些参数仍随请求透传给后端(用
proxy_set_header或默认行为即可)
配合缓存策略提升安全性与可用性
签名 URL 往往有短时效性,缓存时间不宜过长,但可利用 stale 机制缓解后端压力:
- 对 200 响应设较短有效期,例如
proxy_cache_valid 200 2m; - 启用
proxy_cache_use_stale updating error timeout http_500;,避免并发更新或后端故障时大量请求穿透 - 加
add_header X-Cache-Status $upstream_cache_status;方便前端或运维确认是否命中
验证是否生效
部署后用 curl 测试两次相同资源(不同签名):
curl -I "https://example.com/api/data?name=test&sign=aaa&ts=123" curl -I "https://example.com/api/data?name=test&sign=bbb&ts=456"
观察响应头中的 X-Cache-Status:首次为 MISS,第二次应为 HIT,且两个响应内容一致,说明缓存 key 已正确归一化。











