Autenticación LDAP con Spring Security

RECU-0437 (Recurso Manual)
Tabla de contenidos

Descripción

Spring Security es una herramienta que permite automatizar el control de acceso (autenticación y autorización) y sesión de una aplicación. Al estar basado en Spring su configuración y personalización es muy sencilla. Spring Security incluye funcionalidad para autenticar usuarios mediante conexión a LDAP.

La autenticación LDAP en Spring Security se puede dividir a grandes rasgos en las siguientes etapas:

  1. Obtención del DN o “Distinguished Name” del nombre de usuario. Esto suele implicar realizar una consulta en el directorio, a no ser que el mapeo exacto de nombres de usuario a Dns se conozca previamente.
  2. Autenticación de usuario, bien haciendo un binding como este, bien realizando una “comparación remota” de la password del usuario contra la existente en el atributo password de la entrada correspondiente al DN en el directorio.
  3. Carga de la lista de autorizaciones del usuario.

La excepción es cuando el directorio LDAP se usa para consultar información del usuario y autenticación de forma local. Esto puede no ser posible al estar a menudo los directorios configurados con acceso de lectura limitado para el atributo password.

El XML de declaración de beans necesario para agregar esta funcionalidad de LDAP en una aplicación constará de los siguientes elementos:

<bean id="authenticationManager" 
   class="org.springframework.security.providers.ProviderManager">
   <property name="providers">
      <list>
         <!--  ref bean="daoAuthenticationProvider" /-->
         <ref bean="ldapAuthenticationProvider" />
      </list>
   </property>
</bean>

El bean “authenticationManager” normalmente mantiene una referencia un bean "daoAuthenticationProvider" que realiza la autenticación mediante consultas a BD. Esta referencia se sustituye por otra a un bean "ldapAuthenticationProvider". Bean "ldapAuthenticationProvider"

<bean id="ldapAuthenticationProvider"
   class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
   <constructor-arg>
      <ref local="ldap-authenticator" />
   </constructor-arg>
   <property name="userDetailsContextMapper" ref="ldapUserDetailsMapper" />
</bean>

Este bean consta a su vez de otros dos:

  • ldap-authenticator: Se encarga de realizar la autenticación
  • ldapUserDetailsMapper: Si ha tenido éxito la autenticación recibe el contexto asociado al nodo del usuario solicitado para poder generar una instancia de la clase UserDetails de Spring Security, instancia que será lo que se almacene en la sesión como información el usuario.
<bean id="ldap-authenticator"
   class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
   <constructor-arg>
      <ref local="initialDirContextFactory" />
   </constructor-arg>
   <property name="userDnPatterns">
      <list>
         <value>uid={0},ou=people</value>
      </list>
   </property>   
   <property name="userSearch">
      <ref local="userSearch" />
   </property>
</bean>

Se encarga de ejecutar el procedimiento de autenticación. Su configuración es la siguiente:

  • initialDirContextFactory: Para establecer la conexión con el LDAP
  • userDnPatterns: Intenta obtener el DN del usuario mediante localización directa aplicando el nombre de usuario a un patrón.
  • userSearch: Intenta obtener el DN del usuario buscándolo mediante localización directa componiendo el DN a partir del nombre de usuario y un patrón.

Los beans userDnPatterns y userSearch pueden definirse juntos. El ldap-authenticator tratará de localizar al usuario utilizando el primero. Si falla, usará el segundo. En cualquier caso, si ha tenido éxito la localización usará el DN obtenido para ejecutar la autenticación.

<bean id="ldapUserDetailsMapper" class="(clase)">
</bean>

Este bean normalmente usará una clase propia de la aplicación que derive de org.springframework.security.userdetails.ldap.LdapUserDetailsMapper para redefinir el método mapUserFromContext. Este método se encargará de recopilar la información del usuario para crear una instancia de UserDetails, que es la que Spring Security almacena en la sesión.

<bean id="initialDirContextFactory"
   class="org.springframework.security.ldap.DefaultInitialDirContextFactory">
   <constructor-arg value="ldap://host:389/dc=juntadeandalucia,dc=es" />
   <property name="managerDn">
      <value>(usuario de servicio GUIA)</value>
   </property>
   <property name="managerPassword">
      <value>(password)</value>
   </property>
</bean>

Aquí se definen los parámetros básicos de conexión (host, DN base, DN usuario, password).

<bean id="userSearch"
   class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
   <constructor-arg>
      <value>o=personas,o=identidades,o=comundes</value>
   </constructor-arg>
   <constructor-arg>
      <value>(numdoc={0})</value>
   </constructor-arg>
   <constructor-arg>
      <ref local="initialDirContextFactory" />
   </constructor-arg>
   <property name="searchSubtree">
      <value>true</value>
   </property>
</bean>

Este bean trata de obtener el DN del usuario ejecutando una búsqueda con filtro en el LDAP.