2012-04-13 21 views
12

我已經使用Spring Security 3.1實現了LDAP認證。我的security.xml文件發佈在下面。在Spring 3.1中通過IP地址進行身份驗證:最明智的方法是什麼?

我需要改變我的身份驗證過程,以便如果用戶通過「白名單」(保存在數據庫表中)的IP地址訪問站點,則該用戶應該自動使用Spring 3.1進行身份驗證,然後重定向遠離登錄屏幕(不是我的想法,我被告知如此)。

如果用戶不是來自其中一個白名單IP地址,則應該強制他/她在登錄頁面上通過LDAP身份驗證。

我是Spring和Spring Security的新手,所以我去了Spring 3.1 Reference Documentation並閱讀了第一部分。在那裏,我閱讀了如果您有任何特殊認證需求的建議,您應該閱讀Section II Architecture and Implementation。我做到了,非常緩慢並記錄下來。

但是,由於我對所有這些都是陌生的,我不確定我完全理解我需要做什麼以及做什麼是最明智的方式。


更新3:我得到的骨架代碼工作的,這裏是我結束了


通過IP地址驗證我的自定義的AuthenticationProvider實現文件

// Authentication Provider To Authenticate By IP Address With Allowed IPs 
// Stored in a db table 


package acme.com.controller.security; 

//import acme.com.controller.security.CustomUserInfoHolder; 

import org.springframework.security.authentication.AuthenticationProvider; 
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 
import org.springframework.security.core.Authentication; 
import org.springframework.security.core.AuthenticationException; 
import org.springframework.security.web.authentication.WebAuthenticationDetails; 
import org.springframework.security.core.context.SecurityContextHolder; 
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; 
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper; 
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 
import org.springframework.security.core.userdetails.UserDetails; 

import org.apache.log4j.Logger; 


public class CustomIPAddressAuthenticationProvider implements AuthenticationProvider 
{ 

    private static final Logger logger = Logger.getLogger(CustomIPAddressAuthenticationProvider.class); 
    private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); 


    @Override 
    public Authentication authenticate(Authentication authentication) 
    throws AuthenticationException { 


     WebAuthenticationDetails wad = null; 
     String userIPAddress   = null; 
     boolean isAuthenticatedByIP = false; 

     // Get the IP address of the user tyring to use the site 
     wad = (WebAuthenticationDetails) authentication.getDetails(); 
     userIPAddress = wad.getRemoteAddress(); 


     logger.debug("userIPAddress == " + userIPAddress); 

     // Compare the user's IP Address with the IP address in the database 
     // stored in the USERS_AUTHENTICATED_BY_IP table & joined to the 
     // USERS tabe to make sure the IP Address has a current user 
     //isAuthenticatedByIP = someDataObject.hasIPAddress(userIPAddress); 
     isAuthenticatedByIP = true; 


     // Authenticated, the user's IP address matches one in the database 
     if (isAuthenticatedByIP) 
     { 

      logger.debug("isAuthenticatedByIP is true, IP Addresses match"); 
      UserDetails user = null; 


      UsernamePasswordAuthenticationToken result = null; 

      result = new UsernamePasswordAuthenticationToken("John Principal", 
                   "PlaceholderPWE"); 

      result.setDetails(authentication.getDetails()); 

      return result; 
     } 


     // Authentication didn't happen, return null to signal that the 
     // AuthenticationManager should move on to the next Authentication provider 
     return null; 
    } 


    @Override 
    public boolean supports(Class<? extends Object> authentication) 
    { 
     // copied it from AbstractUserDetailsAuthenticationProvider 
     return(UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); 
    } 

} 

My * -security.xml文件

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:s="http://www.springframework.org/schema/security" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 

    <s:http pattern="/login*" security="none"/> 
    <s:http pattern="/search*" security="none"/> 
    <s:http pattern="/css/**" security="none"/> 
    <s:http pattern="/js/**" security="none"/> 
    <s:http pattern="/images/**" security="none"/> 




    <s:http auto-config="true" use-expressions="true"> 
     <s:intercept-url pattern="/**" access="isAuthenticated()" /> 

     <s:form-login login-page="/login" 
      authentication-failure-url="/loginfailed" /> 
     <s:logout logout-success-url="/logout" /> 
    </s:http> 



    <s:ldap-server url = "ldap://ldap-itc.smen.acme.com:636/o=acme.com"/> 


    <bean id="customIPAddressAuthenticationProvider" class="com.acme.controller.security.CustomIPAddressAuthenticationProvider" /> 


    <s:authentication-manager> 
     <!-- Proposed: Custom Authentication Provider: Try To Authenticate BY IP Address First, IF NOT, Authenticate WiTh THE LDAP Authentication Provider --> 
     <s:authentication-provider ref="customIPAddressAuthenticationProvider" /> 
     <s:ldap-authentication-provider user-dn-pattern="uid={0},ou=People"/> 
    </s:authentication-manager> 


</beans> 
+1

這是一個非常糟糕的主意。如果其中一個列入白名單的地址是NAT防火牆地址,該怎麼辦?然後,防火牆後面的所有人(可能會有數百人)將自動進行身份驗證,無論他們是誰。 – 2012-04-13 19:46:52

+1

這不會發生在我們的情況,我已被責令這樣做。 – Steve 2012-04-13 20:58:55

+0

您可能將不得不嘗試您已經提到的方法。如果IP地址列表不必動態更改,則可以在啓動時加載它們。 – 2012-04-14 03:11:37

回答

4

你的做法似乎相當完善,你是正確的思維是,Spring會嘗試每個AuthenticationProvider的,直到它得到一個成功的結果,所以你的情況,你會在LDAP提供商之前定義的基於IP的供應商。

根據您的設置,您可能無法在authentication.getDetails()調用中獲得WebAuthenticationDetails對象。如果是這種情況,您應該將Spring的RequestContextListenerRequestContextFilter添加到您的web.xml中。然後您將能夠通過使用RequestContextHolder類並調用RequestContextHolder.getRequestAttributes()來獲取源IP地址。

你應該只需要實現一個AuthenticationProvider,不需要實現UserDetailsS​​ervice,UserDetails或Authentication類。如果您無法通過IP地址驗證用戶,則應該返回null。在這種情況下,Spring將嘗試LDAP提供程序。如果由於某種原因,您不想將嘗試傳遞給LDAP,則應該拋出一個AuthenticationException,這將會停止進程並最終導致用戶出現403錯誤。

我希望這有助於:)

+0

我根據評論更新了我原來的帖子。我仍然有問題。預先感謝任何提示。 – Steve 2012-04-23 00:45:06

相關問題