2015-04-05 61 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鏈的任何其他過濾器之前添加此過濾器。

相關問題