nginx默认过滤含下划线的Header(如auth_token),因历史安全策略避让CGI变量冲突;可直连后端验证,推荐改用短横线命名(如auth-token),或配置underscores_in_headers on启用。

前端传了自定义 Header,后端却收不到,十有八九是 underscores_in_headers 搞的鬼——它不是 bug,而是 nginx 默认的安全策略。
为什么带下划线的 Header 会被 nginx 丢掉?
nginx 默认会过滤掉所有字段名中含下划线(_)的 HTTP 请求头,比如 auth_token、x_merchant_id、file_last_modified。这不是 HTTP 协议限制(RFC 允许下划线),而是历史原因:为避免与 CGI 环境变量命名冲突(CGI 会把 - 和 _ 都转成下划线),nginx 选择默认禁用下划线字段。
一旦请求经过 nginx(无论是反向代理、静态资源服务,还是前置网关),这些字段就会被静默丢弃,后端 PHP、Laravel、Spring Boot 等完全收不到,日志里也查无此头。
如何确认是不是这个原因?
别急着改代码,先快速验证:
- 用 curl 或 Postman 直连后端(绕过 nginx),看是否能收到该 Header
- 在 nginx 的 access_log 或 error_log 中开启详细日志,观察请求头原始内容
- 在后端加一行调试输出:
print_r(getallheaders());(PHP)或request.getHeaderNames()(Java),确认列表里有没有你的字段 - 检查请求链路中是否存在多层代理(如 CDN、K8s Ingress、公司统一网关),只要其中任意一层没开
underscores_in_headers,就会中断
两种主流解决方案及适用场景
方案一:改 Header 名,推荐优先采用
- 把
auth_token改成auth-token,x_shop_id改成x-shop-id - 符合 HTTP/1.1 字段命名惯例(标准头如
Content-Type、X-Forwarded-For全用短横线) - 无需改服务器配置,兼容所有中间件(Nginx、Apache、CDN、云 WAF)
- 前端和后端同步更新即可,风险低、见效快
方案二:开启 nginx 的 underscores_in_headers
- 在 nginx 配置的
http块或server块中添加:underscores_in_headers on; - 注意:必须 reload nginx 生效,且该指令只作用于当前作用域(子 server 不继承)
- 若使用 K8s Ingress 或云厂商负载均衡,需确认其底层 nginx 是否支持并已启用该配置
- 不建议在公网暴露的入口层开启,存在潜在 CGI 变量混淆风险
其他容易混淆的 Header 丢失场景
别一上来就认定是下划线问题,这几个常见干扰项也要排查:
-
CORS 预检未通过:浏览器发 OPTIONS 请求时,服务端没返回
Access-Control-Allow-Headers包含你的自定义头,后续实际请求就被拦截 -
Feign/OpenFeign 覆盖:Spring Cloud 中多个
RequestInterceptor可能互相覆盖 header,或@Headers注解写法错误 -
大小写敏感陷阱:HTTP 头字段名本应不区分大小写,但某些框架(如部分 Java 容器)严格按字面匹配,
Authorization写成authorization就取不到 -
Token 值含非法字符:Header 值中出现换行符(
\n)、制表符或不可见 Unicode 字符(如 U+200B 零宽空格),会导致整个请求头解析失败
本质上,这是个协议兼容性问题,不是功能缺陷。用短横线替代下划线是最稳妥的实践,既避开 nginx 限制,又更贴近 HTTP 生态规范。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











