瀏覽代碼

Experimental UserDetailsManager interface and some ldap implementation classes.

Luke Taylor 19 年之前
父節點
當前提交
139d8c2f65

+ 25 - 0
sandbox/src/main/java/org/acegisecurity/userdetails/UserDetailsManager.java

@@ -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);
+
+}

+ 50 - 0
sandbox/src/main/java/org/acegisecurity/userdetails/ldap/InetOrgPerson.java

@@ -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());
+
+    }
+}

+ 192 - 0
sandbox/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsManager.java

@@ -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;
+    }
+}