Autenticación de Active Directory usando Spring Security 3.2, Spring Ldap 2.0 y JavaConfig
spring-security active-directory (1)
- Para PartialResultException Debe configurar la referencia de parámetros a "seguir" en su fuente de contexto.
Ej .: https://stackoverflow.com/a/26872236/2718510
Estoy escribiendo una aplicación web que requiere que los usuarios inicien sesión. Mi empresa tiene un servidor de Active Directory que me gustaría utilizar para este propósito. Sin embargo, estoy teniendo problemas para usar Spring para autenticar las credenciales de los usuarios.
Estoy usando Spring Security 3.2.2, Spring Ldap 2.0.1 y Java 1.7.
La aplicación web comienza bien, la autenticación contra la autenticación en memoria también funciona bien, por lo que el resto de mi aplicación parece estar configurado correctamente.
Aquí está mi configuración:
@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
}
}
Cuando trato de iniciar sesión con MY_USERNAME y MY_PASSWORD, se produce un Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
Stacktrace completo:
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
Cuando navego por el AD usando un Ldap-Explorer y busco (&(objectClass=user)(userPrincipalName=MY_USERNAME))
, que Spring hace en ActiveDirectoryLdapAuthenticationProvider: searchForUser (...), devuelve el usuario correcto.
Al ingresar una contraseña no válida, Spring devuelve ActiveDirectoryLdapAuthenticationProvider:200 - Active Directory authentication failed: Supplied password was invalid
. Esto parece estar bien.
¿Falta una pieza para la configuración?
¿Hay algún ejemplo práctico de cómo configurar Spring Ldap para un AD utilizando JavaConfig? La Guía de primavera oficial simplemente describe la forma XML http://docs.spring.io/spring-security/site/docs/3.1.5.RELEASE/reference/ldap.html#ldap-active-directory
Actualización: Acabo de actualizar mi AuthenticationProvider a lo siguiente:
@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;
}
Funciona bien, gracias guido!
Nota: Estados de primavera, que se ignora una PartialResultException. Los docs dicen
Algunos servidores de Active Directory (AD) no pueden seguir automáticamente las referencias, lo que a menudo hace que se genere una PartialResultException en las búsquedas. Puede especificar que se omita PartialResultException estableciendo la propiedad ignorePartialResultException en true.
Tal vez haya una manera de establecer esta propiedad en JavaConfig, también. Simplemente lo ignoré.