UserDetails from LDAP and DB

A drawback of the LDAP authentication approach is, that roles and other user details are only retrieved from the LDAP server (plus it breaks the user counter, as it casts to org.appfuse.model.User). You might have the wish, to define additional properties or assign roles just available in the application scope.

For this purpose I extended the base LdapAuthenticationProvider to integrate with AppFuse and return User objects, carrying merged data from the LDAP directory and the database.

LdapDbAuthenticationProvider

This class actually overrides the methode createUserDetails() of the base Acegi LdapAuthenticationProvider. Two possible scenarios may occur:

  • User not in DB: A new user with the username, the password hash (to compensate LDAP outages) and some default property values will get created.
  • User already in DB: The user gets loaded from the DB, then will be enriched with the Roles retrieved from the LDAP directory.

The class is available here: LdapDbAuthenticationProvider

Changes to the User class

To be able to modify the User class you have to import the AppFuse core classes.

An additional set for the LDAP roles is added to the class:

protected Set<Role> ldapRoles = new HashSet<Role>();
 
/**
 * @return roles from the LDAP directory
 */
@Transient
public Set<Role> getLdapRoles() {
	return ldapRoles;
}
 
/**
 * Adds a role from LDAP directory
 * @param ldapRole
 */
public void addLdapRole(Role role) {
	getLdapRoles().add(role);
}
 
/**
 * Sets the LDAP-Roles
 * @param ldapRoles
 */
public void setLdapRoles(Set<Role> ldapRoles) {
	this.ldapRoles = ldapRoles;
}

Afterwards you have to modify the getAuthorities() method for Acegi, so that all roles get returned:

/**
 * @see org.acegisecurity.userdetails.UserDetails#getAuthorities()
 */
@Transient
public GrantedAuthority[] getAuthorities() {
	GrantedAuthority[] authorities = new GrantedAuthority[roles.size() + ldapRoles.size()];
	int index = 0;
	for (Iterator it = roles.iterator(); it.hasNext(); ) {
		authorities[index] = (GrantedAuthority) it.next();
		index++;
	}
	for (Iterator it = ldapRoles.iterator(); it.hasNext(); ) {
		authorities[index] = (GrantedAuthority) it.next();
		index++;
	}
	return authorities; 
}

Change security.xml

In this file the implementation of the ldapAuthenticationProvider has to be changed to the new class and some additional properties need to be assigned:

<bean id="ldapAuthenticationProvider"
	class="com.company.security.providers.ldap.LdapDbAuthenticationProvider">
[...]
	<property name="userDao" ref="userDao" />
	<property name="roleDao" ref="roleDao" />
	<property name="passwordEncoder" ref="passwordEncoder" />
</bean>
Recent changes RSS feed Creative Commons License Donate Driven by DokuWiki