必须配置 proxy_set_header x-forwarded-proto $scheme; 并确保后端信任该头,否则后端误判协议导致重定向异常、secure cookie 失效;需配合 host、x-forwarded-for 等头,并在 django、flask、spring boot 等框架中启用对应代理信任配置。

必须在 Nginx 的 location 或 server 块中添加 proxy_set_header X-Forwarded-Proto $scheme;,并确保后端框架启用对它的信任解析,否则后端仍会按内部 HTTP 连接误判为 HTTP 协议。
核心配置:用 $scheme 动态透传协议
这一行是关键,不能省略,也不能写死:
-
正确写法:
proxy_set_header X-Forwarded-Proto $scheme;
其中$scheme是 Nginx 内置变量,值自动为http或https,取决于客户端实际访问 Nginx 所用的协议(由listen 80或listen 443 ssl决定) -
常见错误:写成
proxy_set_header X-Forwarded-Proto https;——这会让所有请求(包括 HTTP 访问)都被标记为 HTTPS,导致后端生成 Secure Cookie 失效、重定向跳回 HTTP、CSRF 校验失败等问题 - 该指令需放在
proxy_pass之前,且不能被其他配置(如include的通用文件)意外覆盖
配套转发头:避免协议之外的上下文丢失
单设 X-Forwarded-Proto 不够,后端还原原始请求还需其他关键头:
-
proxy_set_header Host $host;:传递用户访问的原始域名(自动剥离端口),防止后端基于127.0.0.1:3000这类地址生成错误跳转 -
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;:追加式记录 IP 链,兼容 CDN 或多层代理 -
proxy_set_header X-Real-IP $remote_addr;:直连场景下提供最简真实 IP;若前端有可信 CDN,需配合set_real_ip_from和real_ip_header X-Forwarded-For提取 -
proxy_set_header X-Forwarded-Host $host;:显式透传原始 Host,比$http_host更干净(后者可能含端口)
后端必须主动信任并读取该头
Nginx 设置了头,后端不认就等于没设:
-
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) -
Express/Node.js:启用
app.set('trust proxy', true),框架将自动识别X-Forwarded-Proto -
Spring Boot:配置
server.forward-headers-strategy=framework,确保内建支持读取该头
验证是否真正生效
别只改配置,动手确认才可靠:
- 在后端加日志打印
req.headers['x-forwarded-proto'](或等效字段),检查值是否随访问协议变化(HTTP 请求应为http,HTTPS 请求应为https) - 用
curl -I http://your-domain.com和curl -I https://your-domain.com分别测试响应头,观察行为差异 - 触发一个重定向接口(如未登录跳转),检查浏览器 Network 面板中
Location响应头是否生成了正确的协议前缀











