核心答案是后端重定向协议降级:Nginx未透传X-Forwarded-Proto头或Spring Boot未启用转发头解析,导致302跳转返回HTTP地址;需检查access.log中upstream_http_location字段,并配置proxy_set_header与server.forward-headers-strategy。

核心问题在于:用户访问的是 HTTPS,但后端 Spring Boot 生成的重定向(如登录跳转、302)却返回了 HTTP 链接。这不是 Nginx 没配 SSL,而是协议信息在代理链中没传到位或后端没正确识别。
看 access.log 定位原始跳转地址
打开 /var/log/nginx/access.log,重点检查三列:
-
$status:Nginx 返回给浏览器的状态码。若为
302,说明重定向已发出; -
$upstream_status:后端真实返回的状态码。若也是
302,说明是后端主动跳转;若为502或504,说明后端根本没响应成功; -
$upstream_http_location:最关键是它——记录后端响应头里的
Location值。如果出现http://example.com/、http://127.0.0.1:8080/或http://localhost/,就确认协议降级发生了。
快速筛查命令:
awk '$9==302 {print $13}' /var/log/nginx/access.log | grep "^http://" | tail -5
检查 Nginx 是否透传了协议标识
Spring Boot 要知道外面是 HTTPS,必须收到 X-Forwarded-Proto 头。配置必须包含:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
proxy_set_header X-Forwarded-Proto $scheme;—— 把原始协议(https 或 http)传过去; -
proxy_set_header Host $host;—— 不要用$http_host,避免带端口(如example.com:443); -
proxy_set_header X-Real-IP $remote_addr;和proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;—— 这些虽不直接解决跳转,但缺失可能触发后端安全拦截。
这些指令必须写在 location 块内,且位于 proxy_pass 之前或之后均可(主流框架兼容)。
确认 Spring Boot 是否启用转发头解析
光传头没用。Spring Boot 默认不信任这些头,需显式开启:
- 在
application.yml中添加:
server:
forward-headers-strategy: framework
tomcat:
remote-ip-header: x-forwarded-for
protocol-header: x-forwarded-proto
port-header: x-forwarded-port
- 确保
trusted-proxies包含 Nginx 的 IP(如192.168.1.10或使用192.168.1.0/24网段); - 若用内嵌 Tomcat,该配置等效于设置
use-forward-headers: true,否则request.getScheme()仍返回http。
验证与兜底:用 Nginx 重写 Location 响应头
如果后端暂时无法修改,可在 Nginx 层做协议修正:
- 定义映射规则:
map $upstream_http_location $fixed_location {
~^http://(.*) https://$1;
default $upstream_http_location;
}
- 在
location块中加入:
proxy_redirect ~^http://(.*) https://$1;
或更稳妥地(需安装 headers-more-nginx-module):
more_set_headers "Location: $fixed_location";
这能强制把后端发来的 http:// 跳转地址,现场改写为 https://。

















