簡體   English   中英

Spring Security 4.0.0 + ActiveDirectoryLdapAuthenticationProvider + BadCredentialsException PartialResultException

[英]Spring Security 4.0.0 + ActiveDirectoryLdapAuthenticationProvider + BadCredentialsException PartialResultException

我已經在stackoverflow上閱讀了幾乎所有關於Spring / Security / Ldap和ActiveDirectory的內容。 即使我找到了有用的提示和提示,我也無法解決我的問題。

這是:我確實使用用戶服務和自定義登錄頁面配置了Spring Security,一切正常。 然后,我嘗試切換到恰好是ActiveDirectory的最終身份驗證提供程序。

這是我的security-applicationContext.xml(我提醒你這個設置在用戶服務作為身份驗證提供程序時工作正常,因此,文件實際上是導入的,等等):

<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/security"
    xmlns:oauth="http://www.springframework.org/schema/security/oauth"
    xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd http://www.springframework.org/schema/security/oauth http://www.springframework.org/schema/security/spring-security-oauth.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

<!-- Définitions globales de sécurité -->
<global-method-security pre-post-annotations="enabled" />

<!-- Configuration de l'accès et du formulaire -->
<!-- Permettre l'accès libre aux feuilles de style, polices et images -->
<http pattern='/resources/css/**' security="none" />
<http pattern='/resources/fonts/**' security="none" />
<http pattern='/resources/images/**' security="none" />

<http use-expressions="true" access-denied-page="/403" disable-url-rewriting="true">

    <!-- Limitation à une seule session utilisateur concurrente -->
    <session-management invalid-session-url="/identite?time=1">
        <concurrency-control max-sessions="1" expired-url="/identite?time=1" />
    </session-management>

    <!-- Définitions pour le formulaire de la page JSP d'identification -->
    <form-login login-page="/identite" login-processing-url="/identite.proc" default-target-url="/" always-use-default-target="true" authentication-failure-url="/identite?err=1" username-parameter="username" password-parameter="password" />

    <logout logout-url="/logout" logout-success-url="/identite?out=1" delete-cookies="JSESSIONID" invalidate-session="true" />

    <!-- Utiliser un canal chiffré pour les échanges -->
    <intercept-url requires-channel="https" pattern="/identite*" access="permitAll()" />
    <intercept-url requires-channel="https" pattern="/**" access="isAuthenticated()" />
</http>

<!-- Fournisseurs d'identité pour le formulaire (au final, LDAP) -->
<authentication-manager erase-credentials="true">
    <ldap-authentication-provider ref="myADProvider" />
    <!-- This is the user-service authentication provider that is working fine
        <authentication-provider>
        <user-service>
        <user name="Toto" authorities="ROLE_USER, ROLE_ADMIN" password="totototo" />
        </user-service>
        </authentication-provider>
    -->
</authentication-manager>

<b:bean id="myADProvider"
    class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    <b:constructor-arg value="fsappsuni" />
    <b:constructor-arg value="ldap://fsapps.company.uni:389/" />
    <b:property name="convertSubErrorCodesToExceptions" value="true" />
    <b:property name="useAuthenticationRequestCredentials" value="true" />
</b:bean>

在bean myADProvider中,即使我將第一個構造函數參數更改為fsapps.company.uni或company.uni或其他任何內容,它也不會將任何內容更改為以下錯誤。 問題似乎是由於綁定搜索后使用錯誤的過濾器查找類似(&(userPrincipalName = {0})(objectClass = user))而不是(&(sAMAccountName = {0})(objectClass)的事實=用戶))。 由於我無法弄清楚如何在使用LDAP提供程序的情況下更改此設置,因此我切換到LDAP提供程序,嘗試使其無法成功運行,既不會在同一個地方遇到問題。 我還將我的Spring Framework從3.1.2升級到4.1.6.RELEASE和Spring Security從3.1.2升級到4.0.0.RELEASE閱讀后出現了ActiveDirectoryLdapAuthenticationProvider的問題,希望在此期間問題得到解決有關此問題的原始討論與版本3.x有關。

以下是我嘗試使用Active Directory進行身份驗證的LDAP設置配置:

<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/security"
    xmlns:oauth="http://www.springframework.org/schema/security/oauth"
    xsi:schemaLocation="http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.0.xsd
    http://www.springframework.org/schema/security/oauth
    http://www.springframework.org/schema/security/spring-security-oauth.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

<!-- Définitions globales de sécurité -->
<global-method-security pre-post-annotations="enabled" />

<!-- Configuration de l'accès et du formulaire -->
<!-- Permettre l'accès libre aux feuilles de style, polices et images -->
<http pattern='/resources/css/**' security="none" />
<http pattern='/resources/fonts/**' security="none" />
<http pattern='/resources/images/**' security="none" />

<http use-expressions="true" disable-url-rewriting="true">

    <!-- Limitation à une seule session utilisateur concurrente -->
    <session-management invalid-session-url="/identite?time=1">
        <concurrency-control max-sessions="1" expired-url="/identite?time=1" />
    </session-management>

    <!-- Définitions pour le formulaire de la page JSP d'identification -->
    <form-login login-page="/identite" login-processing-url="/identite.proc" default-target-url="/" always-use-default-target="true" authentication-failure-url="/identite?err=1" username-parameter="username" password-parameter="password" />
    <csrf disabled="true" />

    <logout logout-url="/logout" logout-success-url="/identite?out=1" delete-cookies="JSESSIONID" invalidate-session="true" />

    <!-- Utiliser un canal chiffré pour les échanges -->
    <intercept-url requires-channel="https" pattern="/identite*" access="permitAll()" />
    <intercept-url requires-channel="https" pattern="/**" access="isAuthenticated()" />
</http>

<!-- Fournisseurs d'identité pour le formulaire (au final, LDAP) -->
<ldap-server url="ldap://fsapps.company.uni/dc=fsapps,dc=company,dc=uni" port="389" />
<authentication-manager erase-credentials="true">
    <ldap-authentication-provider role-prefix="none"
        user-search-filter="(&amp;(sAMAccountName={0})(objectClass=user))"
        group-search-filter="(&amp;(member={0})(objectClass=group))"
        user-search-base="dc=fsapps,dc=company,dc=uni">
    </ldap-authentication-provider>
    <!-- <authentication-provider ref="myADProvider" ></authentication-provider> -->
</authentication-manager>

<!--
<b:bean id="myADProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    <b:constructor-arg value="fsapps.company.uni" />
    <b:constructor-arg value="ldap://fsapps.company.uni:389/" />
    <b:property name="convertSubErrorCodesToExceptions" value="true" />
    <!- -
    <b:property name="useAuthenticationRequestCredentials" value="true" />
    - ->
</b:bean>
<b:bean id="webSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"></b:bean>
-->

</b:beans>

這次,我將bean配置部分留給了AD提供程序以供參考。 這既不起作用。

那么,我如何將用戶和組搜索路徑傳遞給AD提供程序? 或者,如何配置LDAP提供程序以使用AD並完成身份驗證?

以下是我在日志中使用LDAP設置收到的消息,上面介紹了AD設置(錯誤的憑據主要是由於錯誤的搜索路徑):

2015-04-15 16:19:13,252 DEBUG (o.s.s.a.ProviderManager.authenticate) [http-8443-1] Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider MDC{}
2015-04-15 16:19:13,252 DEBUG (o.s.s.l.a.AbstractLdapAuthenticationProvider.authenticate) [http-8443-1] Processing authentication request for user: ba5glag MDC{}
2015-04-15 16:19:13,252 DEBUG (o.s.s.l.s.FilterBasedLdapUserSearch.searchForUser) [http-8443-1] Searching for user 'myuser', with user search [ searchFilter: '(&(sAMAccountName={0})(objectClass=user))', searchBase: 'dc=fsapps,dc=company,dc=uni', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ] MDC{}
2015-04-15 16:19:13,299 DEBUG (o.s.s.a.DefaultAuthenticationEventPublisher.publishAuthenticationFailure) [http-8443-1] No event was found for the exception org.springframework.security.authentication.InternalAuthenticationServiceException MDC{}
2015-04-15 16:19:13,299 ERROR (o.s.s.w.a.AbstractAuthenticationProcessingFilter.doFilter) [http-8443-1] An internal error occurred while trying to authenticate the user. MDC{}
org.springframework.security.authentication.InternalAuthenticationServiceException: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: [LDAP: error code 1 - 00000000: LdapErr: DSID-0C090627, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, vece(unprintable character here)]; remaining name 'dc=fsapps,dc=company,dc=uni'
        at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:207) ~[spring-security-ldap-4.0.0.RELEASE.jar:?]
        at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:82) ~[spring-security-ldap-4.0.0.RELEASE.jar:?]

我希望我提供所有必需的信息,以便為解決此配置問題提供一些提示和指導。

更新2015-04-16~10:20

我想出了如何使用ActiveDirectoryLdapAuthenticationProvider添加搜索過濾器。 我還和Wireshark一起觀看了我的應用服務器和AD服務器之間的交換,看看實際上做了什么。 以下是我的發現,我相信我對問題的解決方案並不遙遠。 我更新了security-applicationContext.xml,因為我現在集中精力使ActiveDirectoryLdapAuthenticationProvider工作,所以我扔掉了ldap-server的東西。 所以,現在這是一個更清晰的配置:

<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/security"
    xmlns:oauth="http://www.springframework.org/schema/security/oauth"
    xsi:schemaLocation="http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.0.xsd
    http://www.springframework.org/schema/security/oauth
    http://www.springframework.org/schema/security/spring-security-oauth.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

    <!-- Définitions globales de sécurité -->
    <global-method-security pre-post-annotations="enabled" />

    <!-- Configuration de l'accès et du formulaire -->
    <!-- Permettre l'accès libre aux feuilles de style, polices et images -->
    <http pattern='/resources/css/**' security="none" />
    <http pattern='/resources/fonts/**' security="none" />
    <http pattern='/resources/images/**' security="none" />
    <http pattern='/resources/js/**' security="none" />

    <http use-expressions="true" disable-url-rewriting="true">

        <!-- Limitation à une seule session utilisateur concurrente -->
        <session-management invalid-session-url="/identite?expiree=1">
            <concurrency-control max-sessions="1" expired-url="/identite?expiree=1" />
        </session-management>

        <!-- Définitions pour le formulaire de la page JSP d'identification -->
        <form-login login-page="/identite" login-processing-url="/identite.proc" default-target-url="/" always-use-default-target="true" authentication-failure-url="/identite?err=1" username-parameter="username" password-parameter="password" />
        <csrf disabled="true" />

        <logout logout-url="/logout" logout-success-url="/identite?termine=1" delete-cookies="JSESSIONID" invalidate-session="true" />

        <!-- Utiliser un canal chiffré pour les échanges -->
        <intercept-url requires-channel="https" pattern="/identite*" access="permitAll()" />
        <intercept-url requires-channel="https" pattern="/**" access="isAuthenticated()" />
        <access-denied-handler error-page="/erreur403" />
    </http>

    <!-- Fournisseurs d'identité pour le formulaire (au final, LDAP) -->
    <authentication-manager erase-credentials="true">
         <authentication-provider ref="myADProvider" />
    </authentication-manager>

    <b:bean id="myADProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
        <b:constructor-arg value="fsapps.company.uni" />
        <b:constructor-arg value="ldap://fsapps.company.uni:389/" />
        <b:property name="searchFilter" value="(&amp;(sAMAccountName={0})(objectClass=user))" />
        <b:property name="convertSubErrorCodesToExceptions" value="true" />
        <b:property name="useAuthenticationRequestCredentials" value="true" />
    </b:bean>
    <b:bean id="webSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />

</b:beans>

關於配置的評論很少。 在myADProvider bean定義中,構造函數的第一個參數fsapps.company.uni用於以username@fsapps.company.uni形式創建主體,並使用以下形式的baseObject構建搜索請求的baseObject:dc = fsapps, DC =公司,DC = UNI。

第二個構造函數的參數用於建立通信。 name =“searchFilter”的屬性類型的下一個元素將調用ActiveDirectoryLdapAuthenticationProvider類的setSearchFilter()方法來設置搜索過濾器(這是我最初想要取得一些進展)。 因此,它現在設置為搜索(&(sAMAccountName = {0})(objectClass = user))。

通過這種設置,我可以在WireShark中看到LDAP對話,並且綁定成功。 綁定響應是成功的。 接下來,搜索請求也會成功,但不會返回任何結果。 因此,我仍然在我的日志中獲得以下內容:

2015-04-16 10:30:28,201 DEBUG (o.s.s.a.ProviderManager.authenticate) [http-8443-2] Authentication attempt using org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider MDC{}
2015-04-16 10:30:28,201 DEBUG (o.s.s.l.a.AbstractLdapAuthenticationProvider.authenticate) [http-8443-2] Processing authentication request for user: myusername MDC{}
2015-04-16 10:30:28,294 DEBUG (o.s.s.l.SpringSecurityLdapTemplate.searchForSingleEntryInternal) [http-8443-2] Searching for entry under DN '', base = 'dc=fsapps,dc=company,dc=uni', filter = '(&(sAMAccountName={0})(objectClass=user))' MDC{}
2015-04-16 10:30:28,294 INFO (o.s.s.l.SpringSecurityLdapTemplate.searchForSingleEntryInternal) [http-8443-2] Ignoring PartialResultException MDC{}
2015-04-16 10:30:28,310 DEBUG (o.s.s.w.a.AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication) [http-8443-2] Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials MDC{}
2015-04-16 10:30:28,310 DEBUG (o.s.s.w.a.AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication) [http-8443-2] Updated SecurityContextHolder to contain null Authentication MDC{}
2015-04-16 10:30:28,310 DEBUG (o.s.s.w.a.AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication) [http-8443-2] Delegating to authentication failure handler org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@2876b359 MDC{}

我相信我幾乎在那里,但如果有人可以提供任何幫助,我仍然可以使用一些幫助。 仔細檢查后,看起來第一個構造函數的參數用於構造baseObject,而userPrincipalName是我的問題。 在我們的設置中,userPrincipalName使用的域名不是LDAP網址中的域名(即campus.company.com)。 到目前為止,我可以更改參數以匹配用於構建用戶主體的域名。 現在,問題是這將改變必須匹配LDAP url架構的baseObject(即fsapps.company.uni)。

從文檔中,只有一種方法可以設置搜索過濾器,但構造函數可以使用一個,兩個或三個參數。 第三個參數是提供baseObject值。

然后我的問題通過以下配置解決,我必須使用所有可用的setter和構造函數的參數來使其工作。 myADProvider bean定義如下:

    <b:bean id="myADProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
        <b:constructor-arg value="campus.company.com" />
        <b:constructor-arg value="ldap://fsapps.company.uni:389/" />
        <b:constructor-arg value="dc=fsapps,dc=company,dc=uni" />
        <b:property name="searchFilter" value="(&amp;(userPrincipalName={0})(objectClass=user))" />
        <b:property name="convertSubErrorCodesToExceptions" value="true" />
    </b:bean>

在我的情況下,現在可以省略searchFilter屬性,因為我回退了默認值。 盡管對我的設置和問題進行了很長時間的描述。 我希望其他人可以從中受益。

以下是ActiveDirectorLdapAuthenticationProvider類文檔的鏈接: http//docs.spring.io/autorepo/docs/spring-security/4.0.0.RELEASE/apidocs/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider。 HTML

我發現WireShark非常有助於查看應用程序服務器和AD服務器之間發生了什么以調試此問題。

我無法使用Context.REFERRAL =“follow”來解決這個問題,實際上問題在於ActiveDirectoryLdapProvider類的方法searchForUser()的代碼。 在此方法中,使用bindPrincipal調用SpringSecurityLdapTemplate.searchForSingleEntryInternal()方法,該實際上是userPrincipalName,它是由傳遞給第一個參數中的構造函數的參數和用戶名組成的。 因此,即使您將搜索過濾器設置為userPrincipalName以外的任何內容,也會將userPrincipalName作為參數0傳遞。因此,具有sAMAccountName的過濾器將無法與UPN一起使用並拋出異常。

應該修改或擴充searchForUser()以檢測searchFilter需要用戶名而不是UPN,或者提供額外的setter來使用searchFilter的模式設置參數。

但是在沒有修改代碼的情況下,沒有辦法讓這個類在這種情況下正常工作。 這就是我最終做的。 我編寫了自己的類,基本上是原始ActiveDirectoryLdapAUthenticationProvider的副本,對searchForUser()進行了一次簡單的修改,將用戶名而不是bindPrincipal傳遞給searchForSingleEntryInternal()。

你可以輸入你想要的任何搜索過濾器,但強制只使用一個實際上是userPrincipalName而不是其他的參數,這有點廢話。

我遇到了類似的問題並做了一些研究。 在我們的域名為“my.company.com”的AD中,我們似乎有兩組用戶,一組使用UPN格式為user1@my.company.com,另一組使用user2 @ somethingelse。 COM。

當我使用org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider並嘗試使用user1@my.company.com和user2@somethingelse.com對用戶進行身份驗證時 - 根據我傳遞給構造函數的內容,其中只有一個有效對於域名。

我不是AD專家,但是看看微軟科技網文章: https//technet.microsoft.com/en-us/library/cc739093(v = ws.10).aspx看起來像UPN后綴通常是一樣的域名,它不是必須的,可以加上別的后綴。 引用那篇文章

UPN的第二部分(UPN后綴)標識用戶帳戶所在的域。 此UPN后綴可以是DNS域名,林中任何域的DNS名稱,也可以是管理員創建的備用名稱,僅用於登錄目的。 此備用UPN后綴不需要是有效的DNS名稱。

在Active Directory中,默認的UPN后綴是用戶帳戶在其中創建的域的DNS名稱。 在大多數情況下,這是在Internet上注冊為企業域的域名。 使用備用域名作為UPN后綴可以提供額外的登錄安全性,並簡化用於登錄林中另一個域的名稱。

例如,如果您的組織使用按部門和區域組織的深層域樹,則域名可能會很長。 該域中用戶的默認用戶UPN可能是sales.westcoast.microsoft.com。 該域中用戶的登錄名稱為user@sales.westcoast.microsoft.com。 創建UPN后綴“microsoft”將允許同一用戶使用更簡單的user @ microsoft登錄名登錄。 有關用戶帳戶的詳細信息,請參閱用戶和計算機帳戶以及對象名稱。

但我認為ActiveDirectoryLdapAuthenticationProvider.java似乎假設域名與UPN后綴相同。 我對ActiveDirectoryLdapAuthenticationProvider.java進行了本地修復,但沒有做出這樣的假設:

String createBindPrincipal(String username) {
    if (domain == null || username.toLowerCase().endsWith(domain) || username.contains("@")) {
            return username;
    }
    return username + "@" + domain;
}

現在,具有不同UPN后綴的兩個用戶都是可搜索的。 如果我的假設是正確的,我可能會打開一個Spring安全漏洞。

在Spring Security 4.1.1 / SpringBoot 1.4.0環境中,我這樣做(在Java中):

@Configuration
public class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter
{
   public void init (AuthenticationManagerBuilder aAuth) throws Exception
   {

      ActiveDirectoryLdapAuthenticationProvider
              myProvider = new ActiveDirectoryLdapAuthenticationProvider (ldapDomain, ldapUrl);
      aAuth.authenticationProvider (myProvider);
      aAuth.eraseCredentials (false);
   }
}

我沒有遇到任何問題,用戶可以使用sAMAccountName登錄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM