使用Spring Security配置应用程序接受HTTP请求并发送HTTPS响应
我是Spring框架的新手,我已经搜索了与本主题相关的每个可能的SO链接,但可以找到任何适当的解决方案。 我有一个在JBoss Wildfly上运行的应用程序。它位于位于Elastic Load Balancer(ELB)背后的AWS EC2实例。 ELB在其中配置了SSL,以便它只接受来自客户端的HTTPS请求,但是我的应用程序服务器只能通过HTTP与ELB进行通信。我的应用程序使用Spring MVC和Spring Security来进行前端/安全管理。 我的安全context.xml文件如下:使用Spring Security配置应用程序接受HTTP请求并发送HTTPS响应
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<context:property-placeholder location="/WEB-INF/config.properties" />
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.etech.security"> </context:component-scan>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="[email protected]"
authorities="admin" password="xxxxxxxx" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<security:http use-expressions="true">
<security:intercept-url pattern="/" access="isAuthenticated()" />
<security:intercept-url pattern="/dashboard"
access="isAuthenticated()" />
<security:intercept-url pattern="/resources/**" access="permitAll" />
<security:intercept-url pattern="/login" access="permitAll" />
<security:intercept-url pattern="/**" access="denyAll" />
<security:form-login login-page="/login"
authentication-success-handler-ref="asyncAuthenticationSuccessHandler"
authentication-failure-handler-ref="asyncAuthenticationFailureHandler" />
<security:logout logout-url="/logout" logout-success-url="/" />
</security:http>
<bean id="asyncAuthenticationSuccessHandler"
class="com.etech.security.AsyncAuthenticationSuccessHandler">
<constructor-arg ref="supportMailPassword"></constructor-arg>
</bean>
这种设置是,一旦被认证的应用程序返回一个HTTP链接到客户端,客户端无法为ELB访问的问题只允许HTTPS网址。这如下所示:
客户--HTTPS ---> ELB --- HTTP - >应用服务器/应用
客户< --HTTP-- ELB < --- --- HTTP应用服务器/应用
但也应该真正做到这一点,
客户--HTTPS ---> ELB --- HTTP - >应用服务器/应用
客户< --HTTPS-- ELB < - -HTTPS --- AppServer /应用程序
什么是正确的方法呢,我需要使用任何类型的过滤器,将认证/处理后绑定到响应,我可以将响应URL更改为HTTPS?
深入挖掘问题后,我发现这主要是由于Spring Dispatcher Servlet检测到入站连接不安全,即所有连接都是通过HTTP,这将导致所有出站连接都通过HTTP好。
Spring会通过下面的方法调用HttpServletRequest.isSecure()来检测它,因为从ELB到Application Server的连接是通过HTTP而不是HTTPS,所以它总是返回false。
有一个不错的blog post描述这个完全相同的问题,并发布了一个简单的解决方案,我用我自己。
解决方案是使用将放置在过滤器链顶部的过滤器。它会拦截所有传入的请求,用自定义的HttpServletRequest替换入站的HttpServletRequest,这将使isSecure()方法返回true。然后,Spring调度程序Servlet将检测到这一点,并将HTTPS响应发送回客户端。
步骤很简单:
-
创建自定义了HttpServletRequestWrapper
public class CustomWrapper extends HttpServletRequestWrapper { public CustomWrapper(HttpServletRequest request) { super(request); } public boolean isSecure() { return true; } public String getScheme() { return "https"; } }
-
创建过滤器,将用户此包装
public class CustomFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { CustomWrapper wrapper = new CustomWrapper((HttpServletRequest) request); chain.doFilter(wrapper, response); } @Override public void init(FilterConfig arg0) throws ServletException { }
}
在web.xml中,在包含Spring Security Filter链的任何其他过滤器之前添加此过滤器。
你试过这个解决方案吗?http://*.com/questions/8002272/offloading-https-to-load-balancers-with-spring-security? – shazin 2015-04-06 01:24:00
我试过这个解决方案,但由于某些原因,InsecureChannelProcessor无法从ELB中检测到“X-Forwarded-Proto”头,但是SecureChannelProcessor可以。我绕过了Insecure中的头部检查,开始通过安全通道的所有流量,但它仍然将http urls发送回客户端。 – rahsan 2015-04-06 06:32:46