必须显式配置proxy_set_header x-forwarded-proto $scheme,因为nginx默认不透传该头,后端依赖它准确识别客户端原始https协议,否则会误判为http,引发重定向死循环、secure cookie失效及绝对url生成错误。

SSL 卸载后,客户端用 HTTPS 访问 Nginx,Nginx 解密后以 HTTP 转发给后端——这时后端看到的全是 HTTP 请求,会误判协议,导致重定向死循环、Secure Cookie 失效、绝对 URL 生成错误等问题。关键解法就是用 proxy_set_header X-Forwarded-Proto $scheme 把原始协议准确告诉后端。
为什么必须显式设置这一行
Nginx 默认不发送 X-Forwarded-Proto 头。后端框架(如 Django、Spring Boot、Express)依赖它判断用户真实访问方式。不设或设错,就会出现:
- 用户访问
https://example.com,后端却跳转到http://example.com/login - Django 的
SECURE_SSL_REDIRECT失效,或强制跳转引发ERR_TOO_MANY_REDIRECTS - Flask 的
request.scheme始终返回http,导致密码重置链接带错协议 - Spring Boot 生成的 OAuth 回调地址使用 http,被第三方拒绝
正确写法与常见错误
在 location 或 server 块中添加:
proxy_set_header X-Forwarded-Proto $scheme;
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
注意:
-
$scheme是 Nginx 内置变量,值自动为http或https,取决于客户端连接 Nginx 时用的协议(由listen 80或listen 443 ssl决定) - 绝不能写成
proxy_set_header X-Forwarded-Proto https;——这会让所有请求(包括 HTTP)都被标记为 HTTPS,后端逻辑崩溃 - 若 Nginx 前有 CDN(如 Cloudflare、阿里云 WAF),且 CDN 已传该头,应优先用
$http_x_forwarded_proto避免覆盖
配套必须透传的其他头部
单传 X-Forwarded-Proto 不够,后端还需还原完整请求上下文:
-
proxy_set_header Host $http_host;——保留原始 Host 和端口(如api.example.com:443),比$host更可靠 -
proxy_set_header X-Real-IP $remote_addr;——传递真实客户端 IP,用于日志、限流、安全策略 -
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;——支持多层代理链路的 IP 追加记录 -
proxy_set_header X-Forwarded-Port $server_port;——配合协议头,让后端构建正确 URL(尤其在非标准端口如 8443 上)
后端必须启用信任才真正生效
Nginx 设置了头,后端不认等于白配。不同框架启用方式不同,但核心一致:明确告诉框架“来自 Nginx 的 X-Forwarded-* 头是可信的”。
-
Django:设置
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'),并开启USE_X_FORWARDED_HOST = True -
Flask:用
ProxyFix中间件,如app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_for=1) -
Express/Node.js:调用
app.set('trust proxy', true) -
Spring Boot:配置
server.forward-headers-strategy=framework,确保ForwardedHeaderFilter生效
所有框架都要求该配置在路由、认证等中间件之前注册,否则协议信息来不及参与请求处理。










