防伪标记验证靠if+请求头变量实现,非rewrite;nginx将x-signature转为$http_x_signature,需检查存在性及格式(如32位十六进制),并结合x-timestamp校验时间偏差≤300秒。

验证来源请求是否带有合法的防伪标记,本质不是靠 rewrite 完成的,而是用 if + 请求头变量 + 条件拦截实现。rewrite 本身不校验合法性,只负责路径改写;真正做“防伪标记”判断的是对 $http_x_* 类变量的检查与响应控制。
提取并检查防伪请求头字段
Nginx 将所有小写带短横线的请求头自动转为 $http_ 开头的变量(如 X-Signature → $http_x_signature)。需先确认前端按规范传递该头:
- 确保客户端发送的是标准命名(如
X-Signature),避免使用下划线(X_Signature默认被丢弃,除非开启underscores_in_headers on) - 在 location 块中用 if 判断该变量是否存在且非空:
if ($http_x_signature = "") { return 403; } - 若需校验格式(如必须是 32 位十六进制),可用正则:
if ($http_x_signature !~ "^[a-f0-9]{32}$") { return 403; }
结合时间戳与签名逻辑做基础防重放
单靠存在性检查不够,建议搭配时间戳头(如 X-Timestamp)提升防伪强度:
- 要求
X-Timestamp为 Unix 秒级时间,且与服务器时间偏差 ≤ 300 秒:set $ts_diff $time_unix; # 先赋值<br>set $ts_diff "$ts_diff - $http_x_timestamp";<br>if ($http_x_timestamp = "") { return 403; }<br>if ($ts_diff > 300) { return 403; }<br>if ($ts_diff - 注意:Nginx 不支持复杂算术,此处用字符串减法是伪代码示意;实际推荐用
map预处理或交由后端完成完整验签
避免 rewrite 干预导致标记丢失
如果请求经过 rewrite 后转发给后端,要确保防伪头未被覆盖或清空:
- 禁用可能覆盖头的 proxy_set_header 指令(如不要写
proxy_set_header X-Signature "") - 显式透传:
proxy_set_header X-Signature $http_x_signature; - 临时调试可在响应头中回显:
add_header X-Debug-Sign $http_x_signature;,用 curl 查看是否送达
上线前必须做的验证动作
防伪逻辑极易因配置顺序或上下文失效,务必实测:
- 用 curl 发送缺失/非法/过期头的请求,确认返回 403 而非 200 或 500
- 开启
rewrite_log on;和error_log /path/error.log notice;,观察日志中是否有误触发的 if 分支 - 检查 error 日志中是否出现
uninitialized_variable_warn,说明某个$http_x_*变量未定义却参与了判断











