繁体   English   中英

如何让Spring Security在多个域的负载均衡器后面工作?

[英]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和相关配置来解决此问题。 希望对您有帮助。

建议1:

具有负载平衡支持流程的Amazon云环境非常简单。 此处提供了分步教程: 具有Java Web应用程序+ Tomcat +会话粘性的弹性负载平衡(ELB)

建议#2:

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>

资源链接: HTTPS / SSL / Spring Security在负载均衡器和非负载均衡器环境中均无效#424

您应该在LB上设置HTTPS连接,然后在LB和tomcat之间建立适当的TLS连接,以便春天停止哭泣。 您只需要向LB提供一个自签名证书,并使用生成该自签名证书的私钥来设置spring安全模块。

(一个更复杂的选项:正确设置tomcat代理,以强制其将LB的HTTP流封装在HTTPS流中。在代理中设置所有TLS要求:证书,私钥...)

您是否尝试将LB地址作为proxyName? 它可能适合您的情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM