2015-04-05 57 views
1

我是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?

+0

你试过这个解决方案吗?http://stackoverflow.com/questions/8002272/offloading-https-to-load-balancers-with-spring-security? – shazin 2015-04-06 01:24:00

+0

我试过这个解决方案,但由于某些原因,InsecureChannelProcessor无法从ELB中检测到“X-Forwarded-Proto”头,但是SecureChannelProcessor可以。我绕过了Insecure中的头部检查,开始通过安全通道的所有流量,但它仍然将http urls发送回客户端。 – rahsan 2015-04-06 06:32:46

回答

1

深入挖掘问题后,我发现这主要是由于Spring Dispatcher Servlet检测到入站连接不安全,即所有连接都是通过HTTP,这将导致所有出站连接都通过HTTP好。

Spring会通过下面的方法调用HttpServletRequest.isSecure()来检测它,因为从ELB到Application Server的连接是通过HTTP而不是HTTPS,所以它总是返回false。

有一个不错的blog post描述这个完全相同的问题,并发布了一个简单的解决方案,我用我自己。

解决方案是使用将放置在过滤器链顶部的过滤器。它会拦截所有传入的请求,用自定义的HttpServletRequest替换入站的HttpServletRequest,这将使isSecure()方法返回true。然后,Spring调度程序Servlet将检测到这一点,并将HTTPS响应发送回客户端。

步骤很简单:

  1. 创建自定义了HttpServletRequestWrapper

    public class CustomWrapper extends HttpServletRequestWrapper 
    { 
    
        public CustomWrapper(HttpServletRequest request) { 
         super(request); 
    
        } 
    
        public boolean isSecure() 
        { 
         return true; 
        } 
    
        public String getScheme() 
        { 
         return "https"; 
        } 
    } 
    
  2. 创建过滤器,将用户此包装

    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 { 
    
        } 
    

    }

  3. 在web.xml中,在包含Spring Security Filter链的任何其他过滤器之前添加此过滤器。

相关问题