线上环境token丢失排查
AI-摘要
阿狄 GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客
Nginx 反向代理丢失自定义 Header 导致认证失败问题分析
问题描述
在生产环境中,微信小程序登录后无法访问需要认证的 API 接口,返回 401 未登录错误。而同样的代码在本地开发环境运行正常。
现象
- ✅ 登录接口返回 200,成功获取 token
- ✅ 前端正确保存 token 到本地存储
- ✅ 前端在请求头中正确发送 token
- ❌ 后端收不到 token,返回 401 未登录错误
日志表现
登录检查失败: 未能读取到有效Token
未登录异常: 未能读取到有效Token
根本原因
Nginx 默认会丢弃带下划线的自定义 HTTP Header
在这个案例中:
- 前端发送的自定义 token header 名称中包含下划线
- Nginx 反向代理默认配置不转发带下划线的 header
- 导致后端收不到 token,认证失败
Nginx 的 Header 转发规则
| Header 类型 | 默认行为 |
|---|---|
| 标准 HTTP Header(如 Host、User-Agent) | ✅ 自动转发 |
| Authorization Header | ✅ 自动转发 |
| 带下划线的自定义 Header | ❌ 默认丢弃 |
调试过程
第一步:确认后端配置正确
- 对比开发环境和生产环境的 Spring Boot 配置
- 确认 Sa-Token 框架的
isReadHeader=true配置已正确加载 - 后端配置完全一致,问题不在后端
第二步:排查前端代码
- 验证前端正确保存了 token
- 验证前端在请求头中正确发送了 token
- 前端代码也没有问题
第三步:定位 Nginx 问题
在 Nginx 配置中添加调试 header:
location /api/ {
# ... 其他配置 ...
# 调试:记录接收到的 headers
add_header X-Debug-Token $http_custom_token always;
add_header X-Debug-Auth $http_authorization always;
}
通过小程序网络调试工具查看响应头:
- ✅
X-Debug-Auth: Bearer xxx存在 → Authorization header 被正确转发 - ❌
X-Debug-Token为空 → 自定义 header 被 Nginx 丢弃
解决方案
方案一:修改 Nginx 配置(推荐)
在 Nginx 的 server 块中添加配置:
server {
listen 80;
listen 443 ssl;
server_name example.com;
# ✅ 允许转发带下划线的 headers
underscores_in_headers on;
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# ✅ 显式转发自定义 token header
proxy_set_header custom_token $http_custom_token;
}
}
关键点:
underscores_in_headers on;必须放在server块内,不能放在location块内- 在 location 块中使用
proxy_set_header显式转发需要的 header
方案二:修改前端代码
改用标准的 Authorization header,这样 Nginx 会自动转发:
// 原方式(可能被 Nginx 丢弃)
config.header = {
'custom_token': token
}
// 改为标准方式(Nginx 自动转发)
config.header = {
'Authorization': 'Bearer ' + token
}
最佳实践
1. 使用标准 HTTP Header
优先使用标准的 HTTP Header(如 Authorization),避免自定义 header 被代理丢弃的风险。
2. 显式配置代理转发
在反向代理配置中显式指定需要转发的 header:
# 转发所有必要的 headers
proxy_pass_request_headers on;
# 显式转发特定 headers
proxy_set_header Authorization $http_authorization;
proxy_set_header X-Custom-Header $http_x_custom_header;
3. 添加调试 Header
在开发和测试阶段,添加调试 header 帮助排查问题:
add_header X-Debug-Auth $http_authorization always;
add_header X-Debug-Custom $http_custom_token always;
4. 完整的反向代理配置示例
server {
listen 443 ssl http2;
server_name api.example.com;
# 允许下划线 headers
underscores_in_headers on;
location /api/ {
proxy_pass http://backend:8080;
# 转发必要的 headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 显式转发认证相关 headers
proxy_set_header Authorization $http_authorization;
proxy_set_header X-Custom-Auth $http_x_custom_auth;
# 超时配置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
总结
这个问题的关键在于理解 Nginx 反向代理的 Header 转发机制:
- 标准 HTTP Header 会自动转发
- 带下划线的自定义 Header 默认被丢弃
- 需要显式配置才能转发自定义 Header
在设计认证方案时,应该:
- 优先使用标准的
Authorizationheader - 如果必须使用自定义 header,需要在反向代理中显式配置转发
- 在生产环境部署前,充分测试代理层的 header 转发
这个问题在微服务架构中很常见,特别是当认证信息通过自定义 header 传递时,一定要注意代理层的配置。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员小刘
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果