应使用 $scheme://$host 构造绝对重定向URL:location = / { return 301 $scheme://$host/?sso=1; },避免硬编码协议、依赖 $server_name 或拼接 $server_port,确保端口自动省略且适配代理场景。

在 Nginx 中使用绝对路径重定向时,若客户端通过代理、负载均衡或非标准端口(如 8080、8443)访问,而服务端监听的是默认端口(80/443),直接拼接 $host 或 $server_name 容易导致重定向 URL 的端口缺失或错误(例如跳转到 http://example.com:8080/path 而不是 https://example.com/path),进而引发端口映射错乱、混合内容警告或 SSO 失败等问题。
明确指定 scheme 和 port 的绝对重定向
避免依赖自动推导的主机信息,显式构造完整 URL:
- 用
$scheme获取原始请求协议(http或https),而非硬编码 - 用
$host获取 Host 头(更准确反映客户端意图),而非$server_name - **不拼接
$server_port** —— 它返回 Nginx 监听端口,不是客户端看到的端口;应由$scheme隐含决定标准端口(http → :80,https → :443),且现代浏览器会自动省略标准端口 - 对非标准端口场景(如测试环境暴露 8080),需额外判断并手动补全,但生产环境建议统一终止 SSL 在反向代理层,让 Nginx 始终收到
scheme=https
正确写法示例:根路径带参数的绝对重定向
将 / 永久重定向至 https://example.com/?sso=1,且不继承原请求多余端口:
location = / {
return 301 $scheme://$host/?sso=1;
}
说明:
-
location = /精确匹配根路径,避免误匹配子路径 -
return 301比rewrite更轻量、语义清晰,且不会自动追加原始$args -
$scheme://$host/构造标准 URL,浏览器自动省略:80或:443,不会出现https://example.com:443/这类冗余写法 - 结尾的
?明确清空原始查询参数,防止叠加(如从/?ref=abc重定向成/?sso=1&ref=abc)
处理代理后端的实际端口问题
当 Nginx 前有 CDN、ALB 或其他反向代理时,需确保 $scheme 和 $host 反映真实客户端视角:
- 在 proxy 层(如 AWS ALB、Traefik)设置
X-Forwarded-Proto: https和X-Forwarded-Host头 - Nginx 配置中启用信任头解析:
map $http_x_forwarded_proto $real_scheme {
default $http_x_forwarded_proto;
"" $scheme;
}
map $http_x_forwarded_host $real_host {
default $http_x_forwarded_host;
"" $host;
}
<p>server {</p><h1>...</h1><pre class="brush:php;toolbar:false;">location = / {
return 301 $real_scheme://$real_host/?sso=1;
}}
避免常见陷阱
以下写法容易引发端口错乱,应避免:
-
return 301 http://$server_name$request_uri;——$server_name不一定等于 Host 头,$request_uri会带原始参数和端口 -
rewrite ^/$ http://$host:$server_port/?sso=1 permanent;—— 强制拼$server_port,可能暴露内部监听端口(如 8080)给客户端 - 未设
underscores_in_headers on;导致自定义转发头(如X-Forwarded-Host)被忽略











