我们在Apache SSL代理后面的专用appserver上有一个带有嵌入式Tomcat的spring-boot / spring-mvc应用程序 .
代理服务器上的SSL端口为4433,转发到应用服务器上的端口8080 .
所以代理服务器的URL转发如下:
https://proxyserver:4433/appname >>forward>> http://appserver:8080/
运行WITHOUT代理时,首先发生的是
spring-security重定向请求,如:
http://appserver:8080/ >>redirect>> http://appserver:8080/login
通过扩展 WebSecurityConfigurerAdapter
显示登录表单
...
httpSecurity.formLogin().loginPage("/login") ...
...
它在没有代理的情况下工作正常,但是WITH代理需要更改重定向,因此Spring应该重定向到相应的代理URL,如:
http://appserver:8080/ >>redirect>> https://proxyserver:4433/appname/login
但还没有成功 .
我正在尝试应用此解决方案:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-use-tomcat-behind-a-proxy-server(59.8在前端代理服务器后面使用Tomcat)
我们在Apache中配置了mod_proxy,并验证它是否发送了预期的头文件:
X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Host: proxyserver
X-Forwarded-Port: 4433
X-Forwarded-Proto: https
应用程序以参数启动:
export ARG1='-Dserver.tomcat.protocol-header=x-forwarded-proto'
export ARG2='-Dserver.tomcat.remote-ip-header=x-forwarded-for'
java $ARG1 $ARG2 -jar webapp.jar
仍然重定向不起作用 .
它将在本地重定向到 http://appserver:8080/login
,这是客户无法使用的 .
我们需要做些什么来使这个场景有效吗?
EDIT :另外,我担心代理网址中的"/appname"部分 . 在appserver上,应用程序的根目录是"/" . 如何指示在通过代理时,应该将"/appname"包含在发送回客户端的所有URL中?
6 回答
前几天我遇到了同样的问题 . 经过Spring Boot 1.3的一些调试后,我找到了以下解决方案 .
1. 您必须在Apache代理上设置标头:
2. 您必须告诉Spring Boot应用程序使用这些标头 . 所以将以下行放在application.properties(或Spring Boots了解属性的任何其他地方)中:
如果你正确地做了这两件事,你的应用程序发送的每个重定向都会 not 转到http://127.0.0.1:8080/[path]但会自动转到https://www.myapp.com/[path]
更新1.有关此主题的文档是here . 您应该至少阅读它以了解属性
server.tomcat.internal-proxies
,该属性定义了可信任的代理服务器的IP地址范围 .您的代理看起来很好,后端应用程序也是如此,但是它似乎没有看到
RemoteIpValve
已修改的请求 .RemoteIpValve
的默认行为包括代理IP地址的模式匹配(作为安全检查),它仅修改它认为来自有效代理的请求 . Spring Boot中的模式默认为一组众所周知的内部IP地址,如10.*.*.*
和192.168.*.*
,因此如果您的代理不在其中一个上,则需要明确配置它,例如(使用属性文件格式,这意味着您必须双重转义反斜杠) .
如果设置,您可以看到
RemoteIpValve
中发生的情况或在其中设置断点 .
此问题的典型解决方案是让代理处理任何所需的重写 . 例如,在Apache中,您可以使用rewrite_module和/或headers_module来更正标头 . 另一个例子,Nginx在配置上游服务器后自动为您处理此问题和其他类似情况 .
回应评论:
remote_ip_header和protocol_header spring 引导配置值是什么?
让我们暂时忘记Spring Boot . Tomcat是嵌入式servlet容器,它具有一个名为RemoteIpValve的阀门 . 这个阀门是Apache remotip_module的一个端口 . 这个阀门的主要目的是将"useragent which initiated the request as the originating useragent"视为"the purposes of authorization and logging" . 为了使用这种阀门,需要对其进行配置 .
请找到有关此阀门的更多信息here .
Spring Boot方便地通过server.tomcat.remote_ip_header和server.tomcat.protocol_header属性通过application.properties配置此阀门 .
我使用haproxy作为负载均衡器使用以下配置完全相同的情况,这对我来说很有用 . 唯一的问题是客户端IP位于
request.getRemoteAddr()
而不是"X-Forwarded-For"
标头中在application.properties中:
你试过设置吗?
在Spring Boot?
尝试设置重写规则,如:https://proxyserver:4433/appname >> forward >> http://appserver:8080/appname
然后将应用程序上下文设置为“appname”server.context-path = / appname
所以在本地你可以运行http://appserver:8080/appname并通过反向代理通过https://proxyserver:4433/appname访问
由于我使用的是JBOSS,因此更改了standalone.xmJBoss的:
Tomcat将具有类似的配置,以通知Tomcat(proxy-address-forwarding =“true”)以尊重代理转发地址 .