关键是透传并信任x-forwarded-proto头:nginx需设proxy_set_header x-forwarded-proto $scheme;,后端框架须显式启用转发头解析,再用proxy_redirect修正重定向,多层代理时应基于可信ip动态判断协议。

核心是让后端知道“用户实际走的是 HTTPS”,而不是只看 Nginx 自己跟后端之间用的 HTTP 协议。协议丢失不是 Nginx 没转发,而是转发方式不对、后端不信任、或重定向被忽略。
透传 X-Forwarded-Proto 头
这是最关键的一步,必须在 proxy_pass 之前 设置:
-
proxy_set_header X-Forwarded-Proto $scheme;—— $scheme 自动取值 https 或 http,适配多环境,切勿写死成https - 同时补全基础头:
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_Api_Key),需在http块顶部加:underscores_in_headers on;,否则会被丢弃
后端必须主动解析并信任该头
仅传头没用,后端框架默认忽略 X-Forwarded-* 类 Header:
-
Spring Boot:配置
server.forward-headers-strategy=framework(推荐)或=native(需配合 Tomcat 的RemoteIpValve) -
.NET Core:调用
app.UseForwardedHeaders(),并设置KnownProxies和ForwardedHeaders = XForwardedProto -
Tomcat:在
server.xml的Connector中添加protocolHeader="X-Forwarded-Proto"、secure="true" -
PHP / Laravel / Django:分别启用
trustedProxies、TRUSTED_PROXIES或SECURE_PROXY_SSL_HEADER,指定 Nginx 的 IP 并声明信任X-Forwarded-Proto
兜底修正后端返回的错误重定向
即使头传了、后端也读了,某些旧逻辑或第三方库仍可能返回 Location: http://...。Nginx 可在响应发出前强制改写:
- 最常用:
proxy_redirect http:// https://;—— 把所有以http://开头的 Location 替换为https:// - 匹配内网地址:
proxy_redirect ~^http://[^/]+(?::\d+)?/(.*)$ https://$host/$1;—— 提取路径,统一转为公网 HTTPS 地址 - 精确匹配后端地址:
proxy_redirect http://127.0.0.1:8080/ https://$host/;—— 要求协议、IP、端口、斜杠完全一致才生效 - 注意:
proxy_redirect必须放在proxy_pass之后,且不能被后续配置覆盖
进阶:防伪造与多层代理支持
当 Nginx 前面还有 CDN、WAF 或云负载均衡时,$scheme 不再可靠,需基于可信代理 IP 判断真实协议:
- 在
http块中定义可信代理列表:map $remote_addr $trusted_proxy { 203.208.60.1 1; 192.168.10.1 1; default 0; } - 再生成安全协议变量:
map "$trusted_proxy:$http_x_forwarded_proto" $real_scheme_secure { "1:https" "https"; "1:http" "http"; default $scheme; } - 最后用它透传:
proxy_set_header X-Forwarded-Proto $real_scheme_secure;











