2011-08-19 25 views
5

Estamos utilizando la seguridad de primavera para autenticar usuarios de LDAP en nuestra aplicación. La parte de autenticación funciona correctamente pero la parte de autorización no funciona.¿Cómo rellenar las autorizaciones de LDAP del LDAP de Active Directory utilizando la seguridad de Spring?

No podemos recuperar las funciones del usuario del LDAP.

Del libro "Spring Security 3" por Peter Mularien

"Esto se debe a que las tiendas de directorio del grupo de socios activos al atributos en las entradas LDAP de los propios usuarios. Fuera de la caja (a partir de el momento de la publicación), Spring Security no ofrece un LdapAuthoritiesPopulator que puede ser configurado para admitir la estructura de un árbol típico LDAP de Active Directory. "

A continuación se muestra mi archivo de configuración de seguridad de primavera.

<?xml version="1.0" encoding="UTF-8"?> 

<beans:beans xmlns="http://www.springframework.org/schema/security" 
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
          http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"> 

     <http use-expressions="true" > 
     <intercept-url pattern="/resources/**" filters="none" /> 
     <intercept-url pattern="/login" access="permitAll"/> 
     <intercept-url pattern="/**" access="isAuthenticated()" /> 
     <form-login login-page="/login" 
        default-target-url="/home" 
        always-use-default-target="true" 
        authentication-failure-url="/login?login_error=1" /> 
     <logout invalidate-session="true" 
       logout-success-url="/" 
       logout-url="/logout"/> 
    </http> 

    <authentication-manager alias="ldapAuthenticationManager"> 
     <authentication-provider ref="ldapAuthenticationProvider"/> 
    </authentication-manager> 

    <beans:bean id="ldapAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider"> 
     <beans:constructor-arg ref="ldapBindAuthenticator"/> 
     <beans:constructor-arg ref="ldapAuthoritiesPopulator"/> 
     <beans:property name="userDetailsContextMapper" ref="ldapUserDetailsContextMapper"/> 
    </beans:bean> 

    <beans:bean id="ldapServer" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource"> 
     <!-- MS Active Directory --> 
     <beans:constructor-arg value="ldap://localhost:389/dc=myOrg,dc=net"/> 
     <beans:property name="userDn" value="admin"/> 
     <beans:property name="password" value="admin"/> 
     <beans:property name="baseEnvironmentProperties"> 
      <beans:map> 
       <beans:entry key="java.naming.referral" value="follow" /> 
      </beans:map> 
     </beans:property> 
    </beans:bean> 

    <beans:bean id="ldapBindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator"> 
     <beans:constructor-arg ref="ldapServer"/> 
     <beans:property name="userSearch" ref="ldapSearchBean"/> 
    </beans:bean> 

    <beans:bean id="ldapSearchBean" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch"> 
     <!-- MS Active Directory --> 
     <!-- user-search-base; relative to base of configured context source --> 
     <beans:constructor-arg value="ou=Software OU"/> 
     <!-- user-search-filter --> 
     <beans:constructor-arg value="(sAMAccountName={0})"/> 
     <beans:constructor-arg ref="ldapServer"/> 
    </beans:bean> 

    <beans:bean id="ldapAuthoritiesPopulator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator"> 
     <beans:constructor-arg ref="ldapServer" /> 
     <beans:constructor-arg value="" /> 
     <beans:property name="groupSearchFilter" value="(sAMAccountName={0})"/> 
     <beans:property name="groupRoleAttribute" value="memberOf" /> 
     <beans:property name="rolePrefix" value=""/> 
     <beans:property name="searchSubtree" value="true"/> 
     <beans:property name="convertToUpperCase" value="false"/> 
     <beans:property name="ignorePartialResultException" value="true"/> 
    </beans:bean> 

    <beans:bean class="org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper" id="ldapUserDetailsContextMapper"/> 

</beans:beans> 

Por favor ayuda.

+0

¿Qué falta en su código? Aceptar la solución proporcionada/hipervínculo es una cosa, pero señalar la parte faltante sería genial para ayudar a otros (como yo) a tener exactamente el mismo problema. Gracias por compartir tu solución detallada. –

+1

@CharlesMorin Me di cuenta de que mi respuesta era insuficiente, lo siento. Se agregó nuestra configuración Spring para AD. –

+0

@ MarcelStör Gracias. ¿Qué servidor de aplicaciones estás usando? Estoy intentando que funcione lo mismo en JBoss AS 7.2, sin éxito. Echaremos un vistazo a tu configuración. –

Respuesta

2

Es posible que desee echar un vistazo aquí: https://jira.springsource.org/browse/SEC-876. Aunque esta contribución del código fue rechazada, con una respuesta razonable, podría darle pistas.

se utiliza la siguiente configuración:

XML de Spring

<bean id="ldapUserService" class="MyUserDetailService"> 
    <constructor-arg ref="ldapUserSearch"/> 
    <constructor-arg ref="ldapAuthoritiesPopulator"/> 
</bean> 
<bean id="ldapUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch"> 
    <constructor-arg value="OU=FOO-Accounts,OU=FOO,OU=OU-GLOBAL"/> <!-- user search base, RELATIVE TO SERVER CONTEXT (URL & base of configured LDAP server)! --> 
    <constructor-arg value="(sAMAccountName={0})"/> <!-- user search filter --> 
    <constructor-arg ref="ldapServer"/> 
</bean> 
<bean id="ldapAuthoritiesPopulator" class="MyLdapAuthoritiesPopulator"> 
    <constructor-arg ref="ldapServer" /> 
    <constructor-arg value="=OU=SomeFooBar,OU=FOO-Global-Security,OU=FOO-Groups,OU=FOO,OU=OU-GLOBAL" /> <!-- group search base, RELATIVE TO SERVER CONTEXT (URL & base of configured LDAP server)! --> 
    <constructor-arg ref="roleMappings"/> 
    <property name="groupRoleAttribute" value="cn" /> 
    <property name="groupSearchFilter" value="(member={0})" /> 
</bean> 

Populator

Hay una gran cantidad de código propietario que no puedo compartir porque nuestro cliente tiene información adicional en el AD tenemos que extraer. Lo eliminé porque no le preocupa la pregunta. Por lo tanto, este código no se compilará.

public class MyLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopulator { 

    /** 
    * Prefix assigned by Spring Security to each group/role from LDAP. 
    */ 
    public static final String AUTHORITY_ROLE_PREFIX = "ROLE_"; 

    private Properties roleMappings; 
    private Properties invertedRoleMappings; 

    /** 
    * 
    * @param contextSource supplies the contexts used to search for user roles. 
    * @param groupSearchBase if this is an empty string the search will be performed from the root DN 
    * of the context factory. If null, no search will be performed. 
    * @param roleMappings maps logical (internal) role names to names as delivered by LDAP 
    */ 
    @SuppressWarnings("deprecation") 
    public MyLdapAuthoritiesPopulator(final ContextSource contextSource, 
     final String groupSearchBase, 
     final Properties roleMappings) { 
    super(contextSource, groupSearchBase); 
    setConvertToUpperCase(false); 
    setRolePrefix(""); 
    this.roleMappings = roleMappings; 
    this.invertedRoleMappings = invertRoleMappings(); 
    logger.info("Processing LDAP roles based on the following mapping: {}.", roleMappings); 
    } 

    ..... 

    @Override 
    public Set<GrantedAuthority> getGroupMembershipRoles(final String userDn, final String username) { 
    final Set<GrantedAuthority> effectiveGroupMembershipRoles = super.getGroupMembershipRoles(
     userDn, username); 
    return mapEffectiveRolesToApplicationRoles(effectiveGroupMembershipRoles); 
    } 

    /** 
    * Maps effective LDAP roles such as 'foo_boston_dispatcher' or 'foo_boston_readonly' to 
    * FOO internal roles. The internal role (i.e. the {@link GrantedAuthority}) is a combination 
    * of the 'ROLE_' prefix and a {@link Role} enum value. ......... 
    */ 
    Set<GrantedAuthority> mapEffectiveRolesToApplicationRoles(final Set<GrantedAuthority> effectiveGroupMembershipRoles) { 
    logger.info("Processing effective roles from LDAP: {}.", effectiveGroupMembershipRoles); 
    final Set<GrantedAuthority> internalRoles = new HashSet<GrantedAuthority>(); 
    final List<String> effectiveRoleNames = extractRoleNamesFrom(effectiveGroupMembershipRoles); 
    final List<String> unmappedGroupMembershipRoles = new ArrayList<String>(); 
    ...... 
    // in a method invoked here we do something like internalRoles.add(new GrantedAuthority(AUTHORITY_ROLE_PREFIX + role)); 
    ...... 
    logger.info("Created internal roles {}.", internalRoles); 
    logger.trace(
     "The following group membership roles were not mapped to an internal equivalent: {}", 
     unmappedGroupMembershipRoles); 
    return internalRoles; 
    } 

    ...... 

    private List<String> extractRoleNamesFrom(final Collection<GrantedAuthority> authorities) { 
    final List<String> authorityNames = new ArrayList<String>(authorities.size()); 
    for (GrantedAuthority authority : authorities) { 
     authorityNames.add(authority.getAuthority()); 
    } 
    return authorityNames; 
    } 
} 
+0

¿Te importaría compartir tu clase MyLdapAuthoritiesPopulator por favor? Gracias. –

Cuestiones relacionadas