必须在nginx和tomcat两端同时配置x-forwarded-proto透传与remoteipvalve解析,缺一则重定向仍为http;nginx需加proxy_set_header x-forwarded-proto $scheme,tomcat需配全remoteipvalve的protocolheader、remoteipheader和internalproxies。

必须在 Nginx 和 Tomcat 两端同时配置,缺一不可;只改 Nginx 或只改 Tomcat 都会失败。
为什么 Java 应用重定向会变成 HTTP
Tomcat 默认不信任反向代理传来的协议信息,response.sendRedirect() 生成的 Location 头直接使用 request.getScheme(),而这个值在 Nginx 转发后仍是 http(因为 Tomcat 实际收到的是 HTTP 请求)。即使浏览器访问的是 HTTPS,只要 Tomcat 没被告知“原始请求是 HTTPS”,它就会用 HTTP 构造重定向地址。
常见现象:https://example.com/login 提交后跳转到 http://example.com/dashboard,触发混合内容警告或被浏览器拦截。
- 关键判断依据:抓包看响应头
Location: http://... - 不是 Nginx 配置错误,而是 Tomcat 未启用“协议透传”逻辑
- Spring Boot 的
server.forward-headers-strategy=framework也不足以绕过此问题,底层仍依赖 Servlet 容器解析
proxy_set_header X-Forwarded-Proto $scheme 必须存在
这是让 Tomcat 知道原始协议的唯一可信来源。Nginx 必须显式把当前连接的协议($scheme)注入请求头,否则 Tomcat 收不到任何线索。
正确写法(放在 location 或 server 块内):
proxy_set_header X-Forwarded-Proto $scheme;
- 不能写成
X-Forwarded-Proto https—— 硬编码会破坏 HTTP → HTTPS 自动跳转逻辑 - 不能漏掉分号,否则 Nginx 启动报错:
nginx: [emerg] invalid number of arguments in "proxy_set_header" directive - 该指令必须在
proxy_pass之前,否则不生效 - 不要同时设
X-Forwarded-Proto和X-Forwarded-Ssl on,后者已废弃且行为不一致
Tomcat 的 RemoteIpValve 配置不能只写一半
仅靠 Nginx 传头没用,Tomcat 必须主动读取并覆盖原始请求属性。核心是 RemoteIpValve,但必须配全三项:
<valve classname="org.apache.catalina.valves.RemoteIpValve" remoteipheader="X-Forwarded-For" protocolheader="X-Forwarded-Proto" internalproxies="127\.0\.0\.1|10\.0\.0\.0/8|192\.168\.0\.0/16|172\.16\.0\.0/12"></valve>
-
protocolHeader必须设为X-Forwarded-Proto,和 Nginx 传的头名严格一致(大小写敏感) -
internalProxies必须包含 Nginx 所在 IP 或网段,否则 Tomcat 会忽略该头(安全策略,默认只信 localhost) - 如果 Nginx 和 Tomcat 不在同一台机器,
internalProxies里要加 Nginx 的真实出口 IP,例如192\.168\.1\.10 - 别用
RemoteAddrValve或手动写 Filter 替代 —— 它们无法修改request.getScheme()的返回值
额外检查点:避免 proxy_redirect 干扰
Nginx 默认会重写后端返回的 Location 头,若 Tomcat 已正确生成 HTTPS 地址,proxy_redirect 反而可能把它又改回 HTTP。
- 确认是否启用了
proxy_redirect:搜索配置中是否有proxy_redirect http:// https://或proxy_redirect default - 推荐显式关闭:
proxy_redirect off;,让重定向逻辑完全交给 Tomcat 控制 - 如果必须用
proxy_redirect,确保规则匹配 HTTPS 场景,例如:proxy_redirect ~^http://(.*)$ https://$1; - 注意:Spring Boot 的
server.tomcat.remoteip.remote-ip-header配置只是简化 Valve 注册,底层仍依赖RemoteIpValve实际工作
最容易被忽略的是 internalProxies 的正则表达式——少一个反斜杠(如写成 192.168.0.0/16)会导致整个 Valve 失效,且无日志提示。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











