Announcement Announcement Module
Collapse
No announcement yet.
Overriding DefaultLdapAuthoritiesPopulator Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Overriding DefaultLdapAuthoritiesPopulator

    Hi everybody,

    I would like to use ldap authentication with namespace facilities. But actually I'd like to complete the roles list with other roles not located in ldap directory.

    SecurityConfigHandler does setup a org.springframework.security.ldap.userdetails.Defa ultLdapAuthoritiesPopulator class by default.

    This class defines a method called getAdditionalRoles() which is meant to be overridden.

    But HOW can I setup my CustomLDapAothoritiesPopulator???

    So I have these lines in my xml config:

    Code:
    <ldap-authentication-provider
    		user-dn-pattern="cn={0},cn=Users" />
    <ldap-server url="${ldap.server.url}" />
    What about my Custom class to replace the default one hidden in the namespace security configuration?

    Thanks

  • #2
    It is possible to configure custom LDAP authentication provider:

    https://src.springframework.org/svn/...t-security.xml

    Code:
        <bean id="secondLdapProvider" class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
            <s:custom-authentication-provider />
    		<constructor-arg>
    			<bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
    				<constructor-arg ref="contextSource" />
    				<property name="userSearch">
    					<bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    					  <constructor-arg index="0" value="ou=people"/>
    					  <constructor-arg index="1" value="(uid={0})"/>
    					  <constructor-arg index="2" ref="contextSource" />
    					</bean>				
    				</property>
    			</bean>
    		</constructor-arg>
    		<constructor-arg>
    			<bean class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
    				<constructor-arg ref="contextSource" />
    				<constructor-arg value="ou=groups" />
    				<property name="groupSearchFilter" value="(member={0})"/>
    				<property name="rolePrefix" value="ROLE_"/>
    				<property name="searchSubtree" value="true"/>
    				<property name="convertToUpperCase" value="true"/>
    			</bean>
    		</constructor-arg>
        </bean>

    Comment


    • #3
      Thank you

      Thank you very much. It works, it took times because I've had to debug the process, comparing the one(namespace) and the other(xml) configuration.
      I've used the "userDnPatterns" property instead of the "userSearch". Because i couldn't manage to make it work.... but it doesn't matter as it works now:

      Code:
      <b:bean id="contextSource"
      		class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
      		<b:constructor-arg value="${ldap.server.url}" />
      	</b:bean>
      
      	<b:bean id="ldapProvider"
      		class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
      		<custom-authentication-provider />
      		<b:constructor-arg>
      			<b:bean
      				class="org.springframework.security.ldap.authentication.BindAuthenticator">
      				<b:constructor-arg ref="contextSource" />
      				<b:property name="userDnPatterns">
      					<b:list>
      						<b:value>cn={0},cn=Users</b:value>
      					</b:list>
      				</b:property>
      			</b:bean>
      		</b:constructor-arg>
      		<b:constructor-arg>
      			<b:bean
      				class="org.springframework.security.ldap.userdetails.OrmLdapAuthPopulator">
      				<b:constructor-arg ref="contextSource" />
      				<b:constructor-arg value="" />
      				<b:property name="groupRoleAttribute" value="cn" />
      				<b:property name="groupSearchFilter" value="(uniqueMember={0})" />
      				<b:property name="rolePrefix" value="ROLE_" />
      				<b:property name="searchSubtree" value="true" />
      				<b:property name="convertToUpperCase" value="true" />
      				<b:property name="userService" ref="UserService"></b:property>
      			</b:bean>
      		</b:constructor-arg>
      	</b:bean>
      I'm a little disapointed as I expected the bean to able to be overidden within XML configuration. With the propertyOverrideConfigurer or the class name substitution documented at http://static.springsource.org/sprin...rideconfigurer.

      Thanks again.

      Comment


      • #4
        For some reason my custom getAdditionalRoles is not being called. Just to keep it extremely simple, all I'm doing in that method is adding a "ROLE_MEMBER" to the authorities. I'm expecting every authenticated user to be given this role. So here's the simple getAdditionalRoles method:

        Code:
        	@Override
        	protected Set<GrantedAuthority> getAdditionalRoles(DirContextOperations user, String username) {
        		Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
        		authorities.add(new GrantedAuthorityImpl(rolePrefix + "MEMBER"));
        		return authorities;
            }

        And here is my spring security configuration:
        Code:
        <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:s="http://www.springframework.org/schema/security"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
        
            <s:http use-expressions="true">
                <s:intercept-url pattern="/secure/extreme/**" access="hasRole('ROLE_SUPERVISOR')"/>
                <s:intercept-url pattern="/member/**" access="hasRole('ROLE_MEMBER')"/>
                <s:intercept-url pattern="/secure/**" access="isAuthenticated()" />
                <!-- Disable web URI authorization, as we're using <global-method-security> and have @Secured the services layer instead
                <s:intercept-url pattern="/listAccounts.html" access="isRememberMe()" />
                <s:intercept-url pattern="/post.html" access="hasRole('ROLE_TELLER')" />
                -->
                <s:intercept-url pattern="/**" access="permitAll" />
                <s:form-login />
                <s:logout />
                <s:remember-me />
        <!--
            Uncomment to enable X509 client authentication support
                <x509 />
        -->
                <!-- Uncomment to limit the number of sessions a user can have -->
                <s:session-management invalid-session-url="/timeout.jsp">
                    <s:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
                </s:session-management>
        
            </s:http>
        
        
        
            <!-- Simple namespace-based configuration -->
        
            <s:ldap-server ldif="classpath:users.ldif" port="33389"/>
        
            <s:authentication-manager>
                <s:ldap-authentication-provider
                    group-search-filter="member={0}"
                    group-search-base="ou=groups"
                    user-search-base="ou=people"
                    user-search-filter="uid={0}"
                />
                <s:authentication-provider ref='secondLdapProvider' />
            </s:authentication-manager>
        
        
            <!-- Traditional Bean version of the same configuration -->
        
            <!-- This bean points at the embedded directory server created by the ldap-server element above  -->
            <!-- Modified based on Example 8.1 of section 8.1.3.2. Custom Principal and Credentials Management in the Spring LDAP Reference doc -->
        	<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
        		<property name="url" value="ldap://localhost:33389" />
        		<property name="base" value="dc=springframework,dc=org" />
        		<property name="authenticationSource" ref="springSecurityAuthenticationSource" />
        	</bean>
        	<bean id="springSecurityAuthenticationSource"
        		class="org.springframework.security.ldap.authentication.SpringSecurityAuthenticationSource" />
        
            <bean id="secondLdapProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
                <constructor-arg ref="bindAuthenticator"></constructor-arg>
                <constructor-arg ref="esdoAuthoritiesPopulator"></constructor-arg>
            </bean>
        
        	<bean id="bindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
        	    <constructor-arg ref="contextSource" />
        	    <property name="userSearch" ref="userSearch"></property>
        	</bean>
        
        	<bean id="esdoAuthoritiesPopulator" class="esdo.security.ldap.userdetails.EsdoAuthoritiesPopulator">
        	    <constructor-arg ref="contextSource" />
        	    <constructor-arg value="ou=groups" />
        	    <property name="groupSearchFilter" value="(member={0})"/>
        	    <property name="rolePrefix" value="ROLE_"/>
        	    <property name="searchSubtree" value="true"/>
        	    <property name="convertToUpperCase" value="true"/>
        	</bean>
        
        
        	<bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
        	  <constructor-arg index="0" value="ou=people"/>
        	  <constructor-arg index="1" value="(uid={0})"/>
        	  <constructor-arg index="2" ref="contextSource" />
        	</bean>
        
        	<bean id="ldapUserDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
        		<constructor-arg index="0" ref="userSearch" />
        		<constructor-arg index="1" ref="esdoAuthoritiesPopulator" />
              <property name="userDetailsMapper" ref="ldapUserDetailsMapper"></property>
        	</bean>
        
        	<bean id="ldapUserDetailsMapper" class="org.springframework.security.ldap.userdetails.LdapUserDetailsMapper"></bean>
        </beans>

        Using Spring Sec 3.0.2, Spring 3.0.1, Spring Ldap 1.3 on Tomcat 6.0.24 on STS. The logs show that the rod/koala user was not given the ROLE_MEMBER role:

        Code:
        [DEBUG,FilterSecurityInterceptor,http-8080-1] Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@a71a3a25: Principal: org.springframework.security.ldap.userdetails.LdapUserDetailsImpl@56ebfb: Username: rod; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER, ROLE_SUPERVISOR, ROLE_TELLER; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: 700A215EC4F66D606C6948D20CAA20CA; Granted Authorities: ROLE_USER, ROLE_SUPERVISOR, ROLE_TELLER

        Do you guys see any issue with the configuration? I based it off of the spring security ldap sample.

        Comment


        • #5
          i've been stepping through this, and it seems my custom class is not even being called. Am I not wiring this bean properly?

          Code:
          	<bean id="esdoAuthoritiesPopulator" class="esdo.security.ldap.userdetails.EsdoAuthoritiesPopulator">
          	    <constructor-arg ref="contextSource" />
          	    <constructor-arg value="ou=groups" />
          	    <property name="groupSearchFilter" value="(member={0})"/>
          	    <property name="rolePrefix" value="ROLE_"/>
          	    <property name="searchSubtree" value="true"/>
          	    <property name="convertToUpperCase" value="true"/>
          	</bean>

          Comment


          • #6
            You have two LDAP providers configured - one using the namespace and a bean version. If the namespace version authenticates the user or rejects their credentials, the second one will not be called. Remove the namespace one for the time being as it will be simpler to debug.

            Comment


            • #7
              ah, perfect.

              I changed the authentication-manager to this:

              Code:
                  <s:authentication-manager>
                      <s:authentication-provider ref='secondLdapProvider' />
                  </s:authentication-manager>
              instead of this:
              Code:
                  <s:authentication-manager>
                      <s:ldap-authentication-provider
                          group-search-filter="member={0}"
                          group-search-base="ou=groups"
                          user-search-base="ou=people"
                          user-search-filter="uid={0}"
                      />
                      <s:authentication-provider ref='secondLdapProvider' />
                  </s:authentication-manager>

              and it works. It calls my code properly as I expected. Thanks.

              Comment

              Working...
              X