根本原因是Nginx默认不透传协议信息,后端只能看到Nginx转发的内部HTTP请求;需配置proxy_set_header X-Forwarded-Proto $scheme,并确保后端主动解析该头而非直接调用getScheme()。

后端服务拿不到请求协议(比如 HTTPS 还是 HTTP),根本原因是 Nginx 默认不透传协议信息,后端只能看到 Nginx 与它之间那层 HTTP 请求——通常是内部 HTTP,所以协议固定为 http,丢失了客户端真实的访问方式。
确保 Nginx 正确传递协议标识
客户端用 HTTPS 访问 Nginx,Nginx 解密后以 HTTP 转发给后端,这是标准做法。但后端需要知道“原始协议”才能生成正确跳转链接、判断安全上下文等。关键是在 location 或 server 块中显式设置:
-
proxy_set_header X-Forwarded-Proto $scheme;—— 把客户端实际使用的协议(http或https)塞进请求头 -
proxy_set_header X-Forwarded-Port $server_port;—— 补充端口信息,尤其当 Nginx 监听 443 但后端走 8080 时有用 - 确认
proxy_pass指向的是http://backend(不是https://),避免多一层 TLS 干扰
Java 等后端服务需主动读取 X-Forwarded-Proto
光传 header 不够,后端代码必须信任并使用它。例如 Spring Boot 中:
- 在
application.yml加:server.forward-headers-strategy: native(Spring Boot 2.2+) - 或配置
server.tomcat.remote-ip-header: x-forwarded-for和server.tomcat.protocol-header: x-forwarded-proto - 避免直接调用
request.getScheme(),改用request.getRemoteAddr()+request.getHeader("X-Forwarded-Proto")组合判断
检查云环境或前置 WAF 是否清洗了关键 header
如果 Nginx 前面还有一层云负载均衡(如阿里云 SLB、腾讯云 CLB)或 WAF,它们可能默认丢弃 X-Forwarded-Proto。需登录控制台确认:
- 是否开启“透传客户端协议”或“保留 X-Forwarded-* 头”选项
- 部分厂商要求手动开启“HTTPS 卸载后透传协议”功能
- 可用
curl -H "X-Forwarded-Proto: https" http://your-nginx/health测试 Nginx 是否收到该头,再查后端日志是否接收到
验证链路是否完整生效
别只看配置写了没,要端到端验证:
- 用浏览器开发者工具看原始请求是
https://开头 - 在 Nginx access_log 中加
$http_x_forwarded_proto变量,确认该字段有值 - 在后端打印全部请求头,确认
X-Forwarded-Proto存在且值为https - 若仍为
http,重点排查中间设备或后端框架是否覆盖/忽略该 header


















