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é.