Results 1 to 9 of 9

Thread: Problem with: How do I authenticate against LDAP but load user roles from a database

  1. #1

    Default Problem with: How do I authenticate against LDAP but load user roles from a database

    I tried to authenticate against ldap ( succesfully) but I could not load the roles from a dataBase. I read this on the faq:

    How do I authenticate against LDAP but load user roles from a database?

    The LdapAuthenticationProvider bean (which handles normal LDAP authentication in Spring Security) is configured with two separate strategy interfaces, one which performs the authenticatation and one which loads the user authorities, called LdapAuthenticator and LdapAuthoritiesPopulator respectively. The DefaultLdapAuthoritiesPopulator loads the user authorities from the LDAP directory and has various configuration parameters to allow you to specify how these should be retrieved.

    To use JDBC instead, you can implement the interface yourself, using whatever SQL is appropriate for your schema:

    Code:
    public class MyAuthoritiesPopulator implements LdapAuthoritiesPopulator {
        @Autowired
        JdbcTemplate template;
    
        List<GrantedAuthority> getGrantedAuthorities(DirContextOperations userData, String username) {
          List<GrantedAuthority> = template.query("select role from roles where username = ?",
                                                       new String[] {username},
                                                       new RowMapper<GrantedAuthority>() {
            /**
             *  We're assuming here that you're using the standard convention of using the role
             *  prefix "ROLE_" to mark attributes which are supported by Spring Security's RoleVoter.
             */
            public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
              return new GrantedAuthorityImpl("ROLE_" + rs.getString(1);
            }
          }
        }
      }
    You would then add a bean of this type to your application context and inject it into the LdapAuthenticationProvider. This is covered in the section on configuring LDAP using explicit Spring beans in the LDAP chapter of the reference manual. Note that you can't use the namespace for configuration in this case. You should also consult the Javadoc for the relevant classes and interfaces.
    I dont know how to configure my security xml for that

    My dogstoresecurity.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/security"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
    	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/jdbc
    		http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
    		http://www.springframework.org/schema/security 
    		http://www.springframework.org/schema/security/spring-security-3.0.xsd">
    
    
    	<beans:bean id="contextSource"
    		class=" com.packtpub.springsecurity.security.CustomLdapContextSource">
    		<beans:constructor-arg
    			value="ldaps://root:636/dc=root,dc=com,dc=ar" />
    	</beans:bean>
    
    
    	<beans:bean id="ldapAuthProvider"
    		class="com.packtpub.springsecurity.security.CustomLdapAuthentication">
    		<beans:constructor-arg>
    			<beans:bean
    				class="com.packtpub.springsecurity.security.MyAuthoritiesPopulator">
    				<beans:constructor-arg ref="contextSource" />
    				<beans:property name="userDnPatterns">
    					<beans:list>
    						<beans:value>uid={0},ou=people</beans:value>
    					</beans:list>
    				</beans:property>
    			</beans:bean>
    		</beans:constructor-arg>
    
    
    		<beans:constructor-arg>
    			<beans:bean
    				class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
    				<beans:constructor-arg ref="contextSource" />
    				<beans:constructor-arg value="ou=people" />
    				<beans:property name="groupRoleAttribute" value="ou" />
    			</beans:bean>
    		</beans:constructor-arg>
    	</beans:bean>
    
    	<http auto-config="true" use-expressions="true">
    		<intercept-url pattern="/login.do" access="permitAll" />
    		<intercept-url pattern="/*" access="hasRole('ROLE_USER')" />
    		<form-login login-page="/login.do" />
    		<logout logout-url="/logout" logout-success-url="/" />
    		<remember-me key="jbcpPetStore" services-ref="ipTokenBasedRememberMeServicesBean" />
    	</http>
    
    	<authentication-manager alias="authenticationManager">
    		<authentication-provider>
    			<user-service id="userService">
    				<user authorities="ROLE_USER" name="guest" password="guest" />
    			</user-service>
    		</authentication-provider>
    		<authentication-provider ref="ldapAuthProvider" />
    
    	</authentication-manager>
    
    
    	<beans:bean id="dataSource"
    		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<beans:property name="driverClassName">
    			<beans:value>com.mysql.jdbc.Driver</beans:value>
    		</beans:property>
    		<beans:property name="url">
    			<beans:value>jdbc:mysql://url/db?autoReconnect=true
    			</beans:value>
    		</beans:property>
    		<beans:property name="username">
    			<beans:value>root</beans:value>
    		</beans:property>
    		<beans:property name="password">
    			<beans:value>password</beans:value>
    		</beans:property>
    	</beans:bean>
    
    
    
    </beans:beans>
    Does anyone know how to configure my security.xml ??

    Thanks

  2. #2
    Luke Taylor is offline Senior Member Acegi Security System TeamSpring Team
    Join Date
    Aug 2004
    Location
    Glasgow, Scotland
    Posts
    3,449

    Default

    Your configuration is passing two LdapAuthoritiesPopulator instances as the arguments to your CustomLdapAuthentication constructor. I'm guessing that doesn't match the constructor signature.

    Read the LDAP chapter in the manual and try it with the default beans. The first argument to the LdapAuthenticationPorvider constructor is the authenticator (usually a BindAuthenticator instance), the second is the LdapAuthoritiesPopulator instance (your JDBC-based one).
    Spring - by Pivotal
    twitter @tekul

  3. #3

    Default

    Thanks for answering, I changed the populator

    Code:
    	<beans:bean id="ldapAuthProvider"
    		class="com.packtpub.springsecurity.security.CustomLdapAuthentication">
    		<beans:constructor-arg>
    			<beans:bean
    				class="org.springframework.security.ldap.authentication.BindAuthenticator">
    				<beans:constructor-arg ref="contextSource" />
    				<beans:property name="userDnPatterns">
    					<beans:list>
    						<beans:value>uid={0},ou=people</beans:value>
    					</beans:list>
    				</beans:property>
    			</beans:bean>
    		</beans:constructor-arg>
    
    
    		<beans:constructor-arg>
    			<beans:bean
    				class="com.packtpub.springsecurity.security.MyAuthoritiesPopulator">
    				<beans:constructor-arg ref="contextSource" />
    				<beans:constructor-arg value="ou=people" />
    				<beans:property name="groupRoleAttribute" value="ou" />
    			</beans:bean>
    		</beans:constructor-arg>
    	</beans:bean>

    but this error is shown:

    org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'ldapAuthProvider' defined in ServletContext resource [/WEB-INF/dogstore-security.xml]: Cannot create inner bean 'com.packtpub.springsecurity.security.MyAuthoritie sPopulator#11bed71' of type [com.packtpub.springsecurity.security.MyAuthorities Populator] while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'com.packtpub.springsecurity.security.MyAuthoritie sPopulator#11bed71' defined in ServletContext resource [/WEB-INF/dogstore-security.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)
    I think that something is missing here
    Code:
    <beans:constructor-arg>
    			<beans:bean
    				class="com.packtpub.springsecurity.security.MyAuthoritiesPopulator">
    				<beans:constructor-arg ref="contextSource" />
    				<beans:constructor-arg value="ou=people" />
    				<beans:property name="groupRoleAttribute" value="ou" />
    			</beans:bean>
    		</beans:constructor-arg

    MyAuthoritiesPopulator.java is :

    Code:
    public class MyAuthoritiesPopulator implements LdapAuthoritiesPopulator {
    	@Autowired
    	JdbcTemplate template;
    
    	@Override
    	public List<GrantedAuthority> getGrantedAuthorities(
    			DirContextOperations userData, String username) {
    		List<GrantedAuthority> userPerms = template.query(
    				"select role from roles where username = ?",
    				new String[] { username }, new RowMapper<GrantedAuthority>() {
    					/**
    					 * We're assuming here that you're using the standard
    					 * convention of using the role prefix "ROLE_" to mark
    					 * attributes which are supported by Spring Security's
    					 * RoleVoter.
    					 */
    					public GrantedAuthority mapRow(ResultSet rs, int rowNum)
    							throws SQLException {
    						return new GrantedAuthorityImpl("ROLE_"
    								+ rs.getString(1));
    					}
    				});
    		return userPerms;
    	}
    }
    Any idea?
    Last edited by springredfire; Jan 12th, 2011 at 12:42 PM.

  4. #4
    Luke Taylor is offline Senior Member Acegi Security System TeamSpring Team
    Join Date
    Aug 2004
    Location
    Glasgow, Scotland
    Posts
    3,449

    Default

    No, because I don't have access to the class MyAuthoritiesPopulator. Check the source to see what arguments the constructor takes. If it is using a database, then presumably it doesn't need a ContextSource reference, for example.
    Spring - by Pivotal
    twitter @tekul

  5. #5

    Default

    I edited it recently:

    Code:
    public class MyAuthoritiesPopulator implements LdapAuthoritiesPopulator {
    	@Autowired
    	JdbcTemplate template;
    
    	@Override
    	public List<GrantedAuthority> getGrantedAuthorities(
    			DirContextOperations userData, String username) {
    		List<GrantedAuthority> userPerms = template.query(
    				"select role from roles where username = ?",
    				new String[] { username }, new RowMapper<GrantedAuthority>() {
    					/**
    					 * We're assuming here that you're using the standard
    					 * convention of using the role prefix "ROLE_" to mark
    					 * attributes which are supported by Spring Security's
    					 * RoleVoter.
    					 */
    					public GrantedAuthority mapRow(ResultSet rs, int rowNum)
    							throws SQLException {
    						return new GrantedAuthorityImpl("ROLE_"
    								+ rs.getString(1));
    					}
    				});
    		return userPerms;
    	}
    }

  6. #6
    Join Date
    Jan 2008
    Posts
    1,833

    Default

    You do not have a constructor that that accepts a contextSource and a String. Either update your Spring configuration or your constructor. Your spring configuration

    Code:
    <beans:bean
    				class="com.packtpub.springsecurity.security.MyAuthoritiesPopulator">
    				<beans:constructor-arg ref="contextSource" />
    				<beans:constructor-arg value="ou=people" />
    				<beans:property name="groupRoleAttribute" value="ou" />
    			</beans:bean>
    is essentially trying to do this..

    Code:
    new MyAuthoritiesPopulator(contextSource, "ou=people");
    Rob Winch
    Twitter @rob_winch
    Spring Security Lead
    Spring by Pivotal

  7. #7
    Join Date
    Mar 2012
    Posts
    1

    Default MyAuthoritiesPopulator not getting called

    I have my application context as shown below (As per the spring security 3 book by peter ):

    <!-- ldap custom DB Authorites pouplator-->
    <bean id="LdapAuthoritiesPopulator" class="com.xyz.MyAuthoritiesPopulator"/>

    and the class MyAuthoritiesPopulator a copy paste as given in spring FAQ and mentioned in the above post.

    I am wondering why my custom class is not getting called ?

    regards,
    rav

  8. #8

    Default

    You need to wire the beans something like this:

    Code:
    <bean id="ldapAuthProvider"
        class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
     <constructor-arg>
       <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
         <constructor-arg ref="contextSource"/>
         <property name="userDnPatterns">
           <list><value>uid={0},ou=people</value></list>
         </property>
       </bean>
     </constructor-arg>
     <constructor-arg>
       <bean class="com.xyz.MyAuthoritiesPopulator"/>     
     </constructor-arg>
    </bean>
    there are more details here
    Last edited by Camilo Silva; Apr 3rd, 2012 at 09:20 AM.

  9. #9
    Join Date
    Aug 2006
    Posts
    130

    Default

    spring security has this :
    you can use an userdetailsserviceauthoritiespolulator
    which delegates to an userdetailsservice

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •