![](/img/trans.png)
[英]How can I make Spring Security OAuth2 work with load balancer?
[英]How can I get spring security to work behind a load balancer across multiple domains?
我们正在将一个旧的java / spring应用程序移至AWS,因此它位于AWS Application Load Balancer的背后。 Tomcat在端口8080的负载均衡器后面直接运行,并且我们在负载均衡器和tomcat之间使用HTTP。
问题是在这种情况下,spring安全模块无法识别连接是安全的。
我可以通过配置连接来解决此问题:
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
proxyName="single-host.example.com"
secure="true"
scheme="https"
redirectPort="443"
proxyPort="443" />
适用于单个主机名。 但是,我需要它来跨多个主机名工作。
我尝试跳过代理并添加:
server.tomcat.remote_ip_header=X-Forwarded-For
server.tomcat.protocol_header=X-Forwarded-Proto
但这似乎没有任何区别。
在这种情况下,是否有一种方法可以支持多个主机名?
代理请求时,AWS LoadBalancer发送X-Forwarded-Proto标头。
在Tomcat上,将RemoteIpValve配置为具有从这些标头解释的request.secure和其他请求变量。
<Valve className="org.apache.catalina.valves.RemoteIpValve"/>
您还应该在Connector
配置中省略设置proxyName
,因为它应该自动来自阀门。
我有一些解决方法。 因此,我提供了2条建议。 第一个是逐步的图片视图,以解决您的问题。 如果不是,则转到第二个。
第二个是使用X-Forwarded-Proto
和相关配置来解决此问题。 希望对您有帮助。
具有负载平衡支持流程的Amazon云环境非常简单。 此处提供了分步教程: 具有Java Web应用程序+ Tomcat +会话粘性的弹性负载平衡(ELB)
phillipuniverse提供了解决方案。
在Tomcat中配置以下阀门将使request.isSecure()与X-Forwarded-Proto标头一起正常运行:
<Valve className="org.apache.catalina.valves.RemoteIpValve" protocolHeader="X-Forwarded-Proto" />
可以将其添加到<Host>
元素下的Tomcat的server.xml
。
当然,毕竟,有一种非常非常简单的解决方案可以从一开始就解决此问题。 真正需要做的就是从此修改原始通道过滤器:
if ("https".equals(invocation.getHttpRequest().getHeader("X-Forwarded-Proto"))) {
getEntryPoint().commence(invocation.getRequest(), invocation.getResponse());
}
if (invocation.getHttpRequest().isSecure() ||
"https".equals(invocation.getHttpRequest().getHeader("X-Forwarded-Proto"))) {
getEntryPoint().commence(invocation.getRequest(), invocation.getResponse());
}
这里的最终配置应该是这样的:
<bean class="org.broadleafcommerce.common.security.channel.ProtoChannelBeanPostProcessor">
<property name="channelProcessorOverrides">
<list>
<bean class="org.broadleafcommerce.common.security.channel.ProtoInsecureChannelProcessor" />
<bean class="org.broadleafcommerce.common.security.channel.ProtoSecureChannelProcessor" />
</list>
</property>
</bean>
之后,
有些人更喜欢在负载均衡器处终止SSL,而不使用Apache Web服务器。 在这种情况下,您通常会在80/443上的LB处接受流量,然后在8080上将流量路由到Tomcat。
如果您正在使用Spring的端口映射:
<sec:port-mappings>
<sec:port-mapping http="8080" https="443"/>
</sec:port-mappings>
这将不起作用,因为它不会覆盖新的通道处理器中的端口映射。 不过,这是可以使用的配置:
<bean class="org.broadleafcommerce.common.security.channel.ProtoChannelBeanPostProcessor">
<property name="channelProcessorOverrides">
<list>
<bean class="org.broadleafcommerce.common.security.channel.ProtoInsecureChannelProcessor" >
<property name="entryPoint">
<bean class="org.springframework.security.web.access.channel.RetryWithHttpEntryPoint">
<property name="portMapper" ref="portMapper"/>
</bean>
</property>
</bean>
<bean class="org.broadleafcommerce.common.security.channel.ProtoSecureChannelProcessor" >
<property name="entryPoint">
<bean class="org.springframework.security.web.access.channel.RetryWithHttpsEntryPoint">
<property name="portMapper" ref="portMapper"/>
</bean>
</property>
</bean>
</list>
</property>
</bean>
您应该在LB上设置HTTPS连接,然后在LB和tomcat之间建立适当的TLS连接,以便春天停止哭泣。 您只需要向LB提供一个自签名证书,并使用生成该自签名证书的私钥来设置spring安全模块。
(一个更复杂的选项:正确设置tomcat代理,以强制其将LB的HTTP流封装在HTTPS流中。在代理中设置所有TLS要求:证书,私钥...)
您是否尝试将LB地址作为proxyName? 它可能适合您的情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.