核心是nginx透传x-forwarded-proto $scheme并确保后端信任解析该头,同时用proxy_redirect修正错误location响应;否则后端误判协议导致https重定向死循环。

这个问题核心在于后端应用没拿到原始请求的真实协议,不是 Nginx 没转发,而是它转发了、后端却没认或不敢信。
必须让 Nginx 正确透传协议标识
Nginx 作为 HTTPS 入口,与后端通信用的是 HTTP,所以后端看到的 request.scheme 自然就是 http。要让它知道“外面其实是 HTTPS”,就得靠头信息传递:
- 在
location块里加proxy_set_header X-Forwarded-Proto $scheme;—— 这行最关键,$scheme会自动填入https或http - 同时补全基础头:
proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - 别写死
X-Forwarded-Proto https,否则 HTTP 入口或测试环境会出错
后端必须主动信任并解析这些头
光传头没用,Java(如 Tomcat)、.NET、PHP 等默认都忽略 X-Forwarded-*,得显式启用:
Nginx是一款高性能的开源软件,由俄罗斯开发者Igor Sysoev于2004年创建。它最初设计为高效的HTTP Web服务器,现已成为最受欢迎的Web服务器之一。Nginx以事件驱动、非阻塞I/O架构著称,能以极低内存占用处理数万并发连接,特别适合高流量场景。它同时担任反向代理、负载均衡器、HTTP缓存、TCP/UDP代理等多重角色,常用于静态文件服务、SSL终止、请求转发、API网关和微服务
-
Tomcat:修改
server.xml中的Connector,加上protocolHeader="X-Forwarded-Proto"、secure="true"、remoteIpHeader="X-Forwarded-For" -
.NET Core / ASP.NET:在
Startup.cs或Program.cs中配置app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor, KnownProxies = new IPNetwork[] { IPAddress.Parse("127.0.0.1") } }); -
Laravel / Symfony / Django:分别设置
trustedProxies、TRUSTED_PROXIES或SECURE_PROXY_SSL_HEADER,指定 Nginx 的 IP 并启用X-Forwarded-Proto解析
兜底处理重定向中的协议降级
即使后端逻辑已修复,仍可能因旧代码或第三方库返回 Location: http://...。Nginx 可强制改写:
- 用
proxy_redirect替换响应头里的协议:proxy_redirect ~^http://(.*)$ https://$1; - 确保它写在
proxy_pass之后,否则不生效 - 如果后端返回带端口的绝对地址(如
http://localhost:8080/),可更精确匹配:proxy_redirect http://localhost:8080/ https://$host/;
验证是否真正生效
别只看页面跳转结果,要抓包或打印关键值确认:
- 检查响应头
Location是否已是https://开头 - 在后端代码里临时打印:
request.getHeader("X-Forwarded-Proto")和request.getScheme(),两者应一致且为https - 浏览器开发者工具 → Network → 查看跳转请求的原始响应头










