spring-boot HttpServletResponse response.sendRedirect是会跳转到 http而不是https
问题原因分析
Spring Boot 的 sendRedirect 方法在通过 Nginx 代理时,会因缺少协议头信息而默认跳转到 HTTP,导致 HTTPS 请求被重定向到 HTTP,从而引发安全问题。具体原因如下:
- Nginx 代理机制:Nginx 将 HTTPS 请求转发给 Spring Boot 时,仅传递 HTTP 协议头(
X-Forwarded-Proto: http),而 Spring Boot 未识别该头,导致重定向时协议丢失。 - Spring Boot 缺乏协议感知:默认情况下,Spring Boot 无法识别 Nginx 传递的协议头(如
X-Forwarded-Proto),导致重定向时协议被重置为 HTTP。
解决方案
1. Nginx 配置调整
在 Nginx 配置中添加协议头并启用重定向转换:
server {listen 443 ssl;server_name example.com;ssl_certificate /path/to/cert.pem;ssl_certificate_key /path/to/key.pem;location / {proxy_pass http://localhost:8080; # Spring Boot 端口 proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme; # 关键:传递协议头proxy_redirect http:// https://; # 自动转换重定向协议 } }
作用:
proxy_set_header X-Forwarded-Proto $scheme;:将原始协议(HTTPS)传递给 Spring Boot。proxy_redirect http:// https://;:自动将 Spring Boot 返回的 HTTP 重定向转换为 HTTPS。
2. Spring Boot 配置启用协议感知
在 application.properties 中启用协议头处理:
server.forward-headers-strategy=framework server.tomcat.remote-ip-header=X-Forwarded-For server.tomcat.protocol-header=X-Forwarded-Proto
作用:
forward-headers-strategy=framework:启用 Spring Boot 内置的协议头处理机制。protocol-header=X-Forwarded-Proto:指定协议头名称(需与 Nginx 一致)。
3. 可选:自定义重定向过滤器
若上述配置无效,可添加过滤器强制 HTTPS:
import org.springframework.stereotype.Component; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;@Component public class HttpsRedirectFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;String scheme = httpRequest.getHeader("X-Forwarded-Proto");if ("http".equals(scheme)) {String redirectUrl = "https://" + httpRequest.getServerName() + httpRequest.getRequestURI();httpResponse.sendRedirect(redirectUrl);} else {chain.doFilter(request, response);}} }
作用:
- 检查
X-Forwarded-Proto头,若为 HTTP 则强制重定向到 HTTPS。
关键配置说明
- Nginx 必须配置:
proxy_set_header X-Forwarded-Proto $scheme;:传递原始协议头。proxy_redirect http:// https://;:自动转换重定向协议。
- Spring Boot 必须配置:
server.forward-headers-strategy=framework:启用协议头处理。server.tomcat.protocol-header=X-Forwarded-Proto:指定协议头名称。
- 验证步骤:
- 启动应用后,访问 HTTPS 页面,检查重定向 URL 是否为 HTTPS。
- 若仍跳转 HTTP,检查 Nginx 配置是否生效(如
proxy_redirect是否启用)。
总结:通过 Nginx 传递协议头并启用 Spring Boot 的协议感知机制,可确保
sendRedirect方法自动跳转到 HTTPS。若配置无效,可添加自定义过滤器强制 HTTPS。