问题现象
SpringBoot应用中通过如下代码进行请求重定向
response.sendRedirect("/?Authorization=" + token);
目的是重定向到当前地址根路径并带上token,让前端实现自动登录,功能很简单,但是结果请求并没有重定向到我预想的外网地址,而是重定向到了服务器内网IP上,并且端口也是当前springboot应用的端口,而不是外网nginx暴露的端口
问题原因
比较容易想到的原因应该是nginx转发时未配置proxy_set_header
参数,导致应用未获取到外网的IP端口,只需要增加如下配置即可:
location ^~ /api/ {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://172.27.1.12:9097/;
}
但是经过排查并不只是这个原因,分析我们的整个请求链路:
Nginx ----> Spring Cloud Gateway -----> SpringBoot应用
猜测除了Nginx可能这里的Gateway也存在类似的问题,经过排查确实有可能会出现这种情况,Gateway中也有如下的一些配置支持:
spring:
cloud:
gateway:
x-forwarded:
enabled: true
forwarded:
enabled: true
但是Gateway的默认配置都是true,如果没有特地修改,应该也不会是这里的问题
解决方案
最后就剩下springboot应用本身的问题了,找到如下配置:
server:
forward-headers-strategy: framework
这里如果不配置的话默认是none
,就不会处理任何转发头,完全忽略 X-Forwarded-*
头信息,这种只适合没有反向代理或负载均衡器的直接将springboot服务端口暴露访问的情况,我们这里经过2层转发,最好就不适用默认配置了。
另外两种取值:
native:使用底层容器(Tomcat/Jetty/Undertow等)的原生支持处理转发头
framework:使用Spring框架的 ForwardedHeaderFilter
处理转发头
实测两种好像都行,我这里选择了framework
配置好后重启服务,再次尝试请求重定向,果然就重定向到了外网的IP端口上了
评论区