Experimental UserDetailsManager interface and some ldap implementation classes.
This commit is contained in:
parent
1b66467f70
commit
139d8c2f65
|
@ -0,0 +1,25 @@
|
|||
package org.acegisecurity.userdetails;
|
||||
|
||||
/**
|
||||
* An extension of the {@link UserDetailsService} which provides the ability
|
||||
* to create new users and update existing ones.
|
||||
*
|
||||
* @author Luke
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface UserDetailsManager extends UserDetailsService {
|
||||
|
||||
/**
|
||||
* Save details for the supplied user, or update
|
||||
*
|
||||
* @param user
|
||||
*/
|
||||
void createUser(UserDetails user);
|
||||
|
||||
void updateUser(UserDetails user);
|
||||
|
||||
void deleteUser(String username);
|
||||
|
||||
boolean userExists(String username);
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package org.acegisecurity.userdetails.ldap;
|
||||
|
||||
/**
|
||||
* @author Luke
|
||||
* @version $Id$
|
||||
*/
|
||||
public class InetOrgPerson extends LdapUserDetailsImpl {
|
||||
String sn;
|
||||
String cn;
|
||||
|
||||
public String getSn() {
|
||||
return sn;
|
||||
}
|
||||
|
||||
public String getCn() {
|
||||
return cn;
|
||||
}
|
||||
|
||||
public static class Essence extends LdapUserDetailsImpl.Essence {
|
||||
|
||||
public Essence() {
|
||||
}
|
||||
|
||||
public Essence(InetOrgPerson copyMe) {
|
||||
super(copyMe);
|
||||
}
|
||||
|
||||
LdapUserDetailsImpl createTarget() {
|
||||
return new InetOrgPerson();
|
||||
}
|
||||
|
||||
public void setSn(String sn) {
|
||||
((InetOrgPerson)instance).sn = sn;
|
||||
}
|
||||
|
||||
public void setCn(String cn) {
|
||||
((InetOrgPerson)instance).cn = cn;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
InetOrgPerson.Essence p = new InetOrgPerson.Essence();
|
||||
|
||||
p.setSn("Scobbie");
|
||||
|
||||
InetOrgPerson immutablePerson = (InetOrgPerson)p.createUserDetails();
|
||||
System.out.println(immutablePerson.getSn());
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
package org.acegisecurity.userdetails.ldap;
|
||||
|
||||
import org.acegisecurity.userdetails.UserDetailsManager;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
||||
import org.acegisecurity.ldap.LdapUtils;
|
||||
import org.acegisecurity.ldap.ContextSourceInitialDirContextFactory;
|
||||
import org.acegisecurity.providers.encoding.PasswordEncoder;
|
||||
import org.acegisecurity.providers.ldap.authenticator.LdapShaPasswordEncoder;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import net.sf.ldaptemplate.ContextSource;
|
||||
import net.sf.ldaptemplate.LdapTemplate;
|
||||
import net.sf.ldaptemplate.EntryNotFoundException;
|
||||
import net.sf.ldaptemplate.ContextMapper;
|
||||
import net.sf.ldaptemplate.support.DistinguishedName;
|
||||
import net.sf.ldaptemplate.support.DirContextOperations;
|
||||
import net.sf.ldaptemplate.support.DirContextAdapter;
|
||||
|
||||
import javax.naming.Context;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* UserDetails manager. Based on the "Person" sample dao from spring-ldap.
|
||||
*
|
||||
* @author Luke
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LdapUserDetailsManager implements UserDetailsManager {
|
||||
private String usernameAttributeName;
|
||||
private DistinguishedName userDnBase;
|
||||
private LdapTemplate template;
|
||||
|
||||
private String groupBase="cn=groups";
|
||||
private String groupRoleName="cn";
|
||||
private String rolePrefix = "ROLE_";
|
||||
|
||||
private ContextMapper mapper;
|
||||
|
||||
private String[] objectClasses = new String[] {"top", "person", "organizationalPerson", "inetOrgPerson"};
|
||||
|
||||
/** Map of user details properties to ldap attributes */
|
||||
private Map attributeMapping;
|
||||
|
||||
public static void main(String[] args) {
|
||||
ContextSourceInitialDirContextFactory contextFactory = new ContextSourceInitialDirContextFactory("ldap://192.168.101.100:389/dc=acegisecurity,dc=com,dc=au");
|
||||
contextFactory.setManagerDn("uid=acegiman,cn=people,dc=acegisecurity,dc=com,dc=au");
|
||||
contextFactory.setManagerPassword("password");
|
||||
|
||||
LdapUserDetailsManager mgr = new LdapUserDetailsManager(contextFactory);
|
||||
|
||||
InetOrgPerson.Essence user = new InetOrgPerson.Essence();
|
||||
user.setUsername("jerrymouse");
|
||||
user.setSn("User");
|
||||
user.setCn("Test User");
|
||||
PasswordEncoder pwe = new LdapShaPasswordEncoder();
|
||||
user.setPassword(pwe.encodePassword("wheresthecheese", null));
|
||||
|
||||
mgr.updateUser(user.createUserDetails());
|
||||
}
|
||||
|
||||
public LdapUserDetailsManager(ContextSource contextSource) {
|
||||
template = new LdapTemplate(contextSource);
|
||||
userDnBase = new DistinguishedName("cn=users");
|
||||
Map defaultMapping = new HashMap();
|
||||
|
||||
defaultMapping.put("username", "cn");
|
||||
defaultMapping.put("password", "userPassword");
|
||||
|
||||
attributeMapping = Collections.unmodifiableMap(defaultMapping);
|
||||
}
|
||||
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||
DistinguishedName dn = buildDn(username);
|
||||
|
||||
return (UserDetails) template.lookup(dn, mapper);
|
||||
}
|
||||
|
||||
public void createUser(UserDetails user) {
|
||||
template.bind(buildDn(user.getUsername()), getUserContextToBind(user), null);
|
||||
}
|
||||
|
||||
public void updateUser(UserDetails user) throws UsernameNotFoundException {
|
||||
template.rebind(buildDn(user.getUsername()), getUserContextToBind(user), null);
|
||||
}
|
||||
|
||||
public void deleteUser(String username) throws UsernameNotFoundException {
|
||||
DistinguishedName dn = buildDn(username);
|
||||
template.unbind(dn);
|
||||
}
|
||||
|
||||
DirContextOperations getUserContextToBind(UserDetails user) {
|
||||
DirContextAdapter adapter = new DirContextAdapter();
|
||||
|
||||
Map attributesToSet = new HashMap();
|
||||
attributesToSet.put("objectclass", objectClasses);
|
||||
|
||||
BeanWrapperImpl userBean = new BeanWrapperImpl(user);
|
||||
Iterator properties = attributeMapping.keySet().iterator();
|
||||
|
||||
while(properties.hasNext()) {
|
||||
String property = (String) properties.next();
|
||||
String attribute = (String) attributeMapping.get(property);
|
||||
|
||||
List values = (List) attributesToSet.get(attribute);
|
||||
if(values == null) {
|
||||
values = new ArrayList();
|
||||
attributesToSet.put(attribute, values);
|
||||
}
|
||||
|
||||
Object propertyValue = userBean.getPropertyValue(property);
|
||||
Assert.notNull(propertyValue);
|
||||
|
||||
values.add(propertyValue);
|
||||
}
|
||||
|
||||
Iterator attributes = attributesToSet.keySet().iterator();
|
||||
|
||||
while(attributes.hasNext()) {
|
||||
String attributeName = (String) attributes.next();
|
||||
List values = (List) attributesToSet.get(attributeName);
|
||||
adapter.setAttributeValues(attributeName, values.toArray());
|
||||
}
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
public boolean userExists(String username) {
|
||||
DistinguishedName dn = buildDn(username);
|
||||
|
||||
try {
|
||||
Object obj = template.lookup(dn);
|
||||
if (obj instanceof Context) {
|
||||
LdapUtils.closeContext((Context) obj);
|
||||
}
|
||||
return true;
|
||||
} catch(EntryNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
DistinguishedName buildDn(String username) {
|
||||
DistinguishedName dn = new DistinguishedName(userDnBase);
|
||||
|
||||
dn.add(usernameAttributeName, username);
|
||||
|
||||
return dn;
|
||||
}
|
||||
|
||||
public void setGroupBase(String groupBase) {
|
||||
this.groupBase = groupBase;
|
||||
}
|
||||
|
||||
public void setGroupRoleName(String groupRoleName) {
|
||||
this.groupRoleName = groupRoleName;
|
||||
}
|
||||
|
||||
public void setUserDnBase(String userDnBase) {
|
||||
this.userDnBase = new DistinguishedName(userDnBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mapping from property names on the UserDetails object to
|
||||
* directory attributes.
|
||||
*
|
||||
* @param attributeMapping the map, keyed by property name.
|
||||
*/
|
||||
public void setAttributeMapping(Map attributeMapping) {
|
||||
Assert.notNull(attributeMapping.get("username"), "Mapping must contain an entry for 'username'");
|
||||
Assert.notNull(attributeMapping.get("password"), "Mapping must contain an entry for 'password'");
|
||||
usernameAttributeName = (String) attributeMapping.get("username");
|
||||
this.attributeMapping = Collections.unmodifiableMap(attributeMapping);
|
||||
}
|
||||
}
|
||||
|
||||
class UserDetailsContextMapper implements ContextMapper {
|
||||
private Class type;
|
||||
private Map attributeMapping;
|
||||
|
||||
public UserDetailsContextMapper(Map attributeMapping, Class userDetailsType) {
|
||||
type = userDetailsType;
|
||||
this.attributeMapping = attributeMapping;
|
||||
}
|
||||
|
||||
public Object mapFromContext(Object ctx) {
|
||||
DirContextOperations dirContext = (DirContextOperations) ctx;
|
||||
DistinguishedName dn = new DistinguishedName(dirContext.getDn());
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue