web-dev-qa-db-ja.com

Spring Security 3.2、Spring Ldap 2.0、およびJavaConfigを使用したActive Directory認証

ユーザーにログインを要求するWebアプリケーションを作成しています。私の会社には、この目的で利用したいActive Directoryサーバーがあります。しかし、Springを使用してユーザーの資格情報を認証するのに問題があります。

私はSpring Security 3.2.2、Spring Ldap 2.0.1およびJava 1.7。

Webアプリケーションは正常に起動し、InMemory-Authenticationに対する認証も適切に機能するため、アプリケーションの残りの部分は正しく構成されているようです。

これが私の設定です:

@Configuration
@EnableWebSecurity
public class LdapConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        val provider = new ActiveDirectoryLdapAuthenticationProvider("my.domain", "ldap://LDAP_ID:389/OU=A_GROUP,DC=domain,DC=tld");
        provider.setConvertSubErrorCodesToExceptions(true);
        provider.setUseAuthenticationRequestCredentials(true);
        provider.setUseAuthenticationRequestCredentials(true);
        return provider;
    }

    @Bean
    public LoggerListener loggerListener() {
        return new LoggerListener();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // Configuration for Redirects, Login-Page and stuff
    }   
}

MY_USERNAMEとMY_PASSWORDを使用してログインしようとすると、Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentialsが表示されます

完全なスタックトレース:

14:59:00,508 DEBUG UsernamePasswordAuthenticationFilter:205 - Request is to process authentication
14:59:00,509 DEBUG ProviderManager:152 - Authentication attempt using org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider
14:59:00,509 DEBUG ActiveDirectoryLdapAuthenticationProvider:65 - Processing authentication request for user: USERNAME
14:59:00,563 ERROR ActiveDirectoryLdapAuthenticationProvider:133 - Failed to locate directory entry for authenticated user: USERNAME
javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT), data 0, best match of:
    'OU=A_GROUP,DC=domain,DC=tld'
    at com.Sun.jndi.ldap.LdapCtx.mapErrorCode(Unknown Source)
    at com.Sun.jndi.ldap.LdapCtx.processReturnCode(Unknown Source)
    at com.Sun.jndi.ldap.LdapCtx.processReturnCode(Unknown Source)
    at com.Sun.jndi.ldap.LdapCtx.searchAux(Unknown Source)
    at com.Sun.jndi.ldap.LdapCtx.c_search(Unknown Source)
    at com.Sun.jndi.ldap.LdapCtx.c_search(Unknown Source)
    at com.Sun.jndi.toolkit.ctx.ComponentDirContext.p_search(Unknown Source)
    at com.Sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(Unknown Source)
    at javax.naming.directory.InitialDirContext.search(Unknown Source)
    at org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleEntryInternal(SpringSecurityLdapTemplate.Java:208)
    at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.searchForUser(ActiveDirectoryLdapAuthenticationProvider.Java:285)
    at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.doAuthentication(ActiveDirectoryLdapAuthenticationProvider.Java:130)
    at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.Java:80)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.Java:156)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.Java:177)
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.Java:94)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.Java:211)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.Java:110)
    ... a few more

14:59:00,597  WARN LoggerListener:60 - Authentication event AuthenticationFailureBadCredentialsEvent: USERNAME; details: org.sprin[email protected]0: RemoteIpAddUSERNAME: 0:0:0:0:0:0:0:1; SessionId: 1E9401031886F0155F0ACE881CC50A4B; exception: Bad credentials
14:59:00,597 DEBUG UsernamePasswordAuthenticationFilter:348 - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
14:59:00,597 DEBUG UsernamePasswordAuthenticationFilter:349 - Updated SecurityContextHolder to contain null Authentication
14:59:00,597 DEBUG UsernamePasswordAuthenticationFilter:350 - Delegating to authentication failure handler org.springframework.se[email protected]3d876453

Ldap-Explorerを使用してADを参照し、SpringがActiveDirectoryLdapAuthenticationProvider:searchForUser(...)で行う(&(objectClass=user)(userPrincipalName=MY_USERNAME))を検索すると、正しいユーザーが返されます。

無効なパスワードを入力すると、SpringはActiveDirectoryLdapAuthenticationProvider:200 - Active Directory authentication failed: Supplied password was invalidを返します。これで大丈夫そうです。

構成の一部が欠落していますか?

JavaConfigを使用してADのSpring Ldapを構成する方法の実用的な例はありますか?公式のSpringガイドでは、XMLの方法について説明しています http://docs.spring.io/spring-security/site/docs/3.1.5.RELEASE/reference/ldap.html#ldap-active-directory

Update:私のAuthenticationProviderを次のように更新しました:

@Bean
public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
    val provider = new ActiveDirectoryLdapAuthenticationProvider("company.tld", "ldap://LDAP_URL:389");
    provider.setConvertSubErrorCodesToExceptions(true);
    provider.setUseAuthenticationRequestCredentials(true);

    provider.setAuthoritiesMapper(myAuthoritiesMapper()); // see http://comdynamics.net/blog/544/spring-security-3-integration-with-active-directory-ldap/

    provider.setUseAuthenticationRequestCredentials(true);

    return provider;
}

Guidoに感謝します。

注:Springは、PartialResultExceptionは無視されると述べています。ドキュメントは言う

一部のActive Directory(AD)サーバーは照会を自動的に追跡できないため、検索でPartialResultExceptionがスローされることがよくあります。 ignorePartialResultExceptionプロパティをtrueに設定することで、PartialResultExceptionを無視するように指定できます。

たぶん、このプロパティをJavaConfigに設定する方法もあるでしょう。私はそれを無視しました。

18
user3572914
  1. PartialResultExceptionの場合コンテキストソースでパラメーターリフェラルを "follow"に設定する必要があります。

例: https://stackoverflow.com/a/26872236/271851

2