web-dev-qa-db-fra.com

Authentification Active Directory avec Spring Security 3.2, Spring Ldap 2.0 et JavaConfig

J'écris une application Web qui demande aux utilisateurs de se connecter. Ma société possède un serveur Active Directory que je souhaiterais utiliser à cette fin. Cependant, je ne parviens pas à utiliser Spring pour authentifier les informations d'identification des utilisateurs.

J'utilise Spring Security 3.2.2, Spring Ldap 2.0.1 et Java 1.7.

L’application Web démarre bien, l’authentification contre InMemory-Authentication fonctionne également bien, de sorte que le reste de mon application semble être configuré correctement.

Voici ma configuration:

@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
    }   
}

Lorsque j'essaie de me connecter avec MY_USERNAME et MY_PASSWORD, je reçois un Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials

Full Stacktrace:

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.springframework.security.web.authentication.WebAuthenticationDetails@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.security.web.authentication.SimpleUrlAuthenticationFailureHandler@3d876453

Lorsque je navigue dans l'AD à l'aide d'un Ldap-Explorer et que je cherche (&(objectClass=user)(userPrincipalName=MY_USERNAME)), ce que Spring fait dans ActiveDirectoryLdapAuthenticationProvider: searchForUser (...), il renvoie le bon utilisateur. 

Lorsque vous entrez un mot de passe invalide, Spring renvoie ActiveDirectoryLdapAuthenticationProvider:200 - Active Directory authentication failed: Supplied password was invalid. Cela semble être OK.

Une partie de la configuration manque-t-elle?

Existe-t-il des exemples concrets de configuration de Spring Ldap pour un AD utilisant JavaConfig? Le Guide officiel de Spring décrit simplement XML-Way http://docs.spring.io/spring-security/site/docs/3.1.5.RELEASE/reference/ldap.html#ldap-active-directory

Update: Je viens de mettre à jour mon AuthenticationProvider avec les éléments suivants:

@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;
}

Cela fonctionne bien, merci guido!

Remarque: Spring indique qu'une exception PartialResultException est ignorée. Les docs disent

Certains serveurs Active Directory (AD) ne peuvent pas automatiquement suivre les renvois, ce qui conduit souvent à une exception PartialResultException lors des recherches. Vous pouvez spécifier que l'exception PartialResultException doit être ignorée en définissant la propriété ignorePartialResultException sur true.

Peut-être existe-t-il également un moyen de définir cette propriété par rapport à JavaConfig. Je l'ai juste ignoré.

16
user3572914
  1. Pour PartialResultException, vous devez définir le paramètre referral sur "follow" dans votre source de contexte.

Exemple: https://stackoverflow.com/a/26872236/2718510

1
Maciej Czarnecki