问题背景我以如下流程图作为说明
nginx配置如下:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
但是在后端的HttpServletRequest的getScheme()方法一直获取到的协议为http,开始以为是nginx中配置的参数没有生效 proxy_set_header X-Forwarded-Proto $scheme; 但是在nginx的access.log中打印看到确实是输出了https, 所以原因只能是后端没有获取到这个参数,经过多方查找资料,原来是在Spring 后端中,HttpServletRequest.getScheme()
默认获取的是当前Servlet容器接收到的请求协议,而不是X-Forwarded-Proto
头的值。 当应用程序部署在反向代理(例如 Nginx)后面时,反向代理通常使用 HTTP 与后端服务通信,即使原始请求是通过 HTTPS 发送的。在这种情况下,request.getScheme()
将会返回 http
,因为这是反向代理与后端服务之间实际使用的协议。
HttpServletRequest.getScheme()
方法并不自动识别X-Forwarded-Proto
请求头。为了使后端服务能够识别并利用这个头信息,需要配置Spring服务来信任代理服务器并使用X-Forwarded-*
请求头。
在 application.properties
或 application.yml
中,可以设置下面的属性来启用对X-Forwarded-*
请求头的自动处理:
properties复制代码
server.forward-headers-strategy=framework
或者使用 YAML 格式:
server: forward-headers-strategy: framework
启用了ForwardedHeaderFilter
之后,Spring应用将解析X-Forwarded-Proto
、X-Forwarded-Host
和X-Forwarded-Port
请求头,并将这些值用于 HttpServletRequest的getScheme()
、HttpServletRequest的getServerPort()
和 HttpServletRequest的getServerName()
等调用。这样,就可以正确地从 HttpServletRequest
获取到使用了https
协议的信息。
我这里是已经可以正确验证了通过HttpServletRequest的getScheme()方法正确获取到了https协议
14:15:27.912 [476697b6a7c56f3b] [http-nio-8080-exec-1] INFO c.l.a.c.OaFilter - [getFullURL,101] - request.getScheme(): https