proxy_set_header本身不加密,只透传加密认证头;需显式配置$-http_authorization等变量并启用underscores_in_headers,后端须主动解析解密,否则无法识别。

proxy_set_header 本身不负责加密,它只做“透传”——把已存在的、客户端或上游网关提供的加密认证头,原样或稍作处理后发往后端。所谓“加密后的认证头”,通常指 Authorization(如 Bearer eyJhbGciOi...)、自定义加密头(如 X-Encrypted-Token)或经签名/混淆的凭证字段。能否安全、可靠地透传,关键在三点:头字段是否被 Nginx 默认丢弃、变量是否能正确提取、后端是否能识别并解密。
必须显式声明,否则默认丢弃
Nginx 默认过滤掉 Authorization、Proxy-Authorization 等敏感头,也忽略含下划线或非常规命名的自定义头(如 X-Encrypted-Auth)。
你需要手动配置:
# 启用下划线支持(若头名含下划线,如 X_Encrypted_Auth) underscores_in_headers on; # 提取并透传加密认证头 proxy_set_header Authorization $http_authorization; proxy_set_header X-Encrypted-Token $http_x_encrypted_token; proxy_set_header X-Signed-Payload $http_x_signed_payload;
注意变量命名规则:
-
$http_authorization→ 对应请求头Authorization(大小写不敏感,Nginx 统一转为小写+下划线) -
$http_x_encrypted_token→ 对应请求头X-Encrypted-Token(横线转下划线,全小写) - 这些指令必须放在
proxy_pass之前,否则变量为空
区分来源,避免覆盖或污染
不是所有请求都该带加密头。比如:
- 前端直连 Nginx 的登录接口,可能携带原始
Authorization; - 内部服务调用或灰度网关注入的,可能是
X-Encrypted-Token; - 某些场景需降级(如无头时补默认密钥)。
可用 if 或 map 控制透传逻辑:
# 方式1:按请求头是否存在决定是否透传
if ($http_authorization) {
proxy_set_header Authorization $http_authorization;
}
# 方式2:用 map 做白名单校验(防伪造)
map $http_x_encrypted_token $valid_encrypted_token {
default "";
"~^[a-zA-Z0-9+/]*={0,2}$" $http_x_encrypted_token; # 粗略 Base64 格式校验
}
proxy_set_header X-Encrypted-Token $valid_encrypted_token;
后端必须主动解析,不能依赖框架自动行为
Nginx 只是“快递员”,不参与加解密。后端需:
- 显式读取对应 header(如
request.headers.get("X-Encrypted-Token")) - 调用自有解密模块(如 AES 解密、JWT 验证、HMAC 校验)
-
不信任
Authorization头直接用于用户身份判断,除非确认该头由可信网关注入且未被客户端篡改
常见错误:
- Spring Boot 默认忽略
Authorization,需手动request.getHeader("Authorization") - Flask/Werkzeug 中
request.authorization只解析 Basic/Bearer,加密 token 需自行解析 - PHP 中用
$_SERVER['HTTP_X_ENCRYPTED_TOKEN'],而非$_SERVER['REDIRECT_HTTP_X_ENCRYPTED_TOKEN']
补充安全建议
- 若加密头来自前端浏览器,务必配合
SameSite、SecureCookie 及 CSP 降低 XSS 泄露风险 - 不在日志中记录完整加密头(如
log_format中避免$http_authorization) - 在
location块中限制仅/api/等路径透传,静态资源路径(如/assets/)一律不转发
不复杂但容易忽略











