2012-03-02 206 views
0

(上下文:我是一位經驗豐富的程序員,但是對於LDAP,AD和Spring來說是新的。)如何配置Spring Security身份驗證來處理複雜的Active Directory/LDAP帳戶樹?

我們是Windows商店,因此我們所有的身份驗證都是使用Active Directory完成的。我們正在嘗試集成使用Java編寫的第三方產品,因此它使用Spring Security完成所有身份驗證。到目前爲止,這麼好 - 他們之前已經完成了整合,並且網上有很多關於如何設置的交易。

問題是,我們的AD設置有點複雜:特別是,我們的用戶帳戶存在於AD/LDAP樹中的各個節點中。舉一個簡單的例子,說的LDAP樹是這個樣子:

DC=my-domain,DC=com 
+ CN=Users 
++ CN=user1,CN=Users,DC=my-domain,DC=com 
+ CN=Staff 
++ CN=user2,CN=Staff,DC=my-domain,DC=com 

的事情是,所有的我已經找到了例子讓我驗證要麼 USER1或USER2,但不能同時使用。也就是說,下面的XML片段將致力於反對在「組」定義的角色身份驗證用戶1:

<security:ldap-server url="ldap://my-domain.com:389" manager-dn="CN=manager_svc,OU=System Users,DC=my-domain,DC=com" manager-password="MyPa55w0rd"/> 

<security:ldap-authentication-provider 
      user-dn-pattern="" 
      user-search-base="CN=Users,DC=my-domain,DC=com" 
      user-search-filter="(&amp;(sAMAccountName={0})(objectclass=user))" 
      group-search-base="OU=Groups,DC=mydomain,DC=com" 
      group-search-filter="member={0}" 
      /> 

但不會驗證用戶2,因爲他不會在用戶搜索基礎相匹配。相反,我可以將用戶搜索基地更改爲CN=Staff,DC=my-domain,DC=com,這將適用於用戶2,但不適用於用戶1。

所以問題是,我如何使分散在AD/LDAP樹中的用戶帳戶的搜索工作?我能想象兩種可能,但我還沒有想出如何做到既尚未:

  • ,一方面,如果我可以讓用戶搜索基礎的多值,可以輕鬆地解決了我的問題,正確的:我只是把所有可能找到用戶帳戶的位置。到目前爲止,我所做的所有嘗試都遇到了一個或另一個錯誤,但我仍在試驗。

  • OTOH,有搜索的子樹範圍。我可以在交互式LDAP工具中看到,搜索可以是單層或者是子樹。就我所知,開箱即用的Spring是單層的。我可以看到底層的FilterBasedLdapUserSearch類有一個setSearchSubtree()方法,看起來像我想要的,但是我找不到一種方法將其設置爲true。 (現在,讓我們假定它是不可行的改變底層的Java程序。)

第一種選擇將是理想的,因爲它可能是更有效的,但如果這是不可能的,第二是,我懷疑我們可以使它工作。

我懷疑第二種方法可能使用棘手的豆類駭客,但我幾乎不知道豆類,所以我寧願不自己一頭栽入這些叢林。有沒有人有一個好的配方推薦?

感謝很多你可以提供任何指導......

回答

3

你可以嘗試從域根搜索,如果這是可行的,儘管這可能會導致問題與AD。

或者,使用明確的bean configuration可能是您的最佳選擇。您可以將自定義LdapUserSearch實施注入到BindAuthenticator bean中,該bean將在所有必需的位置進行搜索。如果您查看文檔中的示例,則會顯示FilterBasedLdapUserSearch配置。你可以使用其中的一些,或者從頭開始自己實現接口。這裏有一個快速的黑客爲例:

public class CustomLdapSearch implements LdapUserSearch { 
    public static final String SAM_FILTER="(&(sAMAccountName={0})(objectclass=user))" 

    final LdapUserSearch users; 
    final LdapUserSearch staff; 

    public CustomLdapSearch(BaseLdapPathContextSource contextSource) { 
     users = new FilterBasedLdapUserSearch("CN=Users,DC=my-domain,DC=com", SAM_FILTER, contextSource); 
     staff = new FilterBasedLdapUserSearch("CN=Staff,DC=my-domain,DC=com", SAM_FILTER, contextSource); 

    } 

    public DirContextOperations searchForUser(String username) { 
     try { 
      return users.searchForUser(username); 
     } catch(UsernameNotFoundException e) { 
      return staff.searchForUser(username); 
     } 
    } 
} 

然後BindAuthenticator配置更改爲:

<bean class="org.springframework.security.ldap.authentication.BindAuthenticator"> 
<constructor-arg ref="contextSource"/> 
<property name="userSearch" ref="customSearch"/> 
</bean> 

<bean id="customSearch" class="CustomLdapSearch"> 
<constructor-arg ref="contextSource"/> 
</bean> 
+0

此答案有幫助,但它有問題。例如:當你應該使用LdapUserSearch時,你將「users」和「staff」聲明爲LdapSearch。你也宣佈他們是最終的,但沒有設置任何東西。 – fivedogit 2015-05-12 14:23:00

+0

謝謝,我已經更新了代碼。這些字段在構造函數中設置。 – 2015-05-17 19:31:46

0

我已經做了使用FilterBasedLdapUserSearch中帶有彈簧安全2.0.x的類似的東西 - 在用戶進行傳播跨多個節點:

<bean id="ldapUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch"> 
    <constructor-arg value=""/> <!-- optional sub-tree here --> 
    <constructor-arg value="(&amp;(sAMAccountName={0})(objectclass=user))"/> 
    <constructor-arg ref="contextSource"/> 
</bean> 


<bean id="ldapAuthProvider" 
     class="org.springframework.security.providers.ldap.LdapAuthenticationProvider"> 
    <constructor-arg> 
     <bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator"> 
      <constructor-arg ref="contextSource"/> 
      <property name="userSearch" ref="ldapUserSearch"/> 
     </bean> 
    </constructor-arg> 
    <property name="userDetailsContextMapper" ref="userDetailsContextMapper"/> 
</bean> 


<bean id="contextSource" 
     class="org.springframework.security.ldap.DefaultSpringSecurityContextSource"> 
    <constructor-arg value="ldap://localhost:10389/CN=Users,DC=my-domain,DC=com"/> 
<!-- you may or may not need to connect with an account that can search --> 
    <!--<property name="userDn" value="uid=admin,ou=system"/>--> 
    <!--<property name="password" value="secret"/>--> 
</bean> 
2

我解決了這個用searchBase與空字符串值(本使用root作爲searchbase,就像預定義規則的答案),但我也必須將屬性「引用」設置爲「跟隨」,否則我得到了PartialResultException!

DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(...); 
contextSource.setReferral("follow"); 
相關問題