浏览代码

Introduce LDAPUserDetails.

Luke Taylor 19 年之前
父节点
当前提交
db042046e9

+ 30 - 0
core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetails.java

@@ -0,0 +1,30 @@
+package org.acegisecurity.userdetails.ldap;
+
+import org.acegisecurity.userdetails.UserDetails;
+
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.Control;
+
+/**
+ * @author Luke Taylor
+ * @version $Id$
+ */
+public interface LdapUserDetails extends UserDetails {
+    /**
+     * @return the DN of the entry for this user's account.
+     */
+    String getDn();
+
+    /**
+     * @return the attributes for the user's entry in the directory (or a subset of them,
+     * depending on what was retrieved).
+     */
+    Attributes getAttributes();
+
+    /**
+     * Returns any LDAP response controls (as part of a user authentication process, for example).
+     *
+     * @return an array of LDAP Control instances, never null
+     */
+    Control[] getControls();
+}

+ 183 - 0
core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsImpl.java

@@ -0,0 +1,183 @@
+package org.acegisecurity.userdetails.ldap;
+
+import org.acegisecurity.GrantedAuthority;
+
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.ldap.Control;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * A UserDetails implementation which is used internally by the Ldap services.
+ *
+ * It also contains the user's distinguished name and a set of attributes that
+ * have been retrieved from the Ldap server.
+ * <p>
+ * An instance may be created as the result of a search, or when user information
+ * is retrieved during authentication.
+ * </p>
+ * <p>
+ * An instance of this class will be used by the <tt>LdapAuthenticationProvider</tt>
+ * to construct the final user details object that it returns.
+ * </p>
+ *
+ * @author Luke Taylor
+ * @version $Id$
+ */
+public class LdapUserDetailsImpl implements LdapUserDetails {
+
+    private static final GrantedAuthority[] NO_AUTHORITIES = new GrantedAuthority[0];
+    private static final Control[] NO_CONTROLS = new Control[0];
+
+    //~ Instance fields ========================================================
+
+    private String dn;
+    private Attributes attributes = new BasicAttributes();
+    private String username;
+    private String password;
+    private boolean enabled = true;
+    private boolean accountNonExpired = true;
+    private boolean credentialsNonExpired = true;
+    private boolean accountNonLocked = true;
+    private GrantedAuthority[] authorities = NO_AUTHORITIES;
+    private Control[] controls = NO_CONTROLS;
+
+    //~ Constructors ===========================================================
+
+    protected LdapUserDetailsImpl() {
+    }
+
+    //~ Methods ================================================================
+
+    public String getDn() {
+        return dn;
+    }
+
+    public Attributes getAttributes() {
+        return attributes;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public boolean isAccountNonExpired() {
+        return accountNonExpired;
+    }
+
+    public boolean isCredentialsNonExpired() {
+        return credentialsNonExpired;
+    }
+
+    public boolean isAccountNonLocked() {
+        return accountNonLocked;
+    }
+
+    public GrantedAuthority[] getAuthorities() {
+        return authorities;
+    }
+
+    public Control[] getControls() {
+        return controls;
+    }
+
+    //~ Inner classes ==========================================================
+
+    /** Variation of essence pattern. Used to create mutable intermediate object */
+    public static class Essence {
+
+        LdapUserDetailsImpl instance = new LdapUserDetailsImpl();
+
+        List mutableAuthorities = new ArrayList();
+
+        public Essence() {
+        }
+
+        public Essence(LdapUserDetails copyMe) {
+            instance.dn = copyMe.getDn();
+            instance.attributes = copyMe.getAttributes();
+            instance.username = copyMe.getUsername();
+            instance.password = copyMe.getPassword();
+            instance.enabled = copyMe.isEnabled();
+            instance.accountNonExpired = copyMe.isAccountNonExpired();
+            instance.credentialsNonExpired = copyMe.isCredentialsNonExpired();
+            instance.accountNonLocked = copyMe.isAccountNonLocked();
+            instance.controls = copyMe.getControls();
+            mutableAuthorities = Arrays.asList(copyMe.getAuthorities());
+        }
+
+        public Essence setDn(String dn) {
+            instance.dn = dn;
+            return this;
+        }
+
+        public Essence setAttributes(Attributes attributes) {
+            instance.attributes = attributes;
+            return this;
+        }
+
+        public Essence setUsername(String username) {
+            instance.username = username;
+            return this;
+        }
+
+        public Essence setPassword(String password) {
+            instance.password = password;
+            return this;
+        }
+
+        public Essence setEnabled(boolean enabled) {
+            instance.enabled = enabled;
+            return this;
+        }
+
+        public Essence setAccountNonExpired(boolean accountNonExpired) {
+            instance.accountNonExpired = accountNonExpired;
+            return this;
+        }
+
+        public Essence setCredentialsNonExpired(boolean credentialsNonExpired) {
+            instance.credentialsNonExpired = credentialsNonExpired;
+            return this;
+        }
+
+        public Essence setAccountNonLocked(boolean accountNonLocked) {
+            instance.accountNonLocked = accountNonLocked;
+            return this;
+        }
+
+        public Essence setAuthorities(GrantedAuthority[] authorities) {
+            mutableAuthorities = Arrays.asList(authorities);
+
+            return this;
+        }
+
+        public Essence addAuthority(GrantedAuthority a) {
+            mutableAuthorities.add(a);
+
+            return this;
+        }
+
+        public GrantedAuthority[] getGrantedAuthorities() {
+            return (GrantedAuthority[])mutableAuthorities.toArray(new GrantedAuthority[0]);
+        }
+
+        public LdapUserDetails createUserDetails() {
+            //TODO: Validation of properties
+
+            instance.authorities = getGrantedAuthorities();
+
+            return instance;
+        }
+    }
+}

+ 82 - 0
core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapper.java

@@ -0,0 +1,82 @@
+package org.acegisecurity.userdetails.ldap;
+
+import org.acegisecurity.ldap.LdapEntryMapper;
+import org.acegisecurity.GrantedAuthorityImpl;
+import org.springframework.util.Assert;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.naming.directory.Attributes;
+import javax.naming.directory.Attribute;
+import javax.naming.NamingException;
+import javax.naming.NamingEnumeration;
+
+/**
+ * @author Luke Taylor
+ * @version $Id$
+ */
+public class LdapUserDetailsMapper implements LdapEntryMapper {
+    private final Log logger = LogFactory.getLog(LdapUserDetailsMapper.class); 
+
+    private String passwordAttributeName = "userPassword";
+
+    private String[] roleAttributes = null;
+
+    private String rolePrefix = "ROLE_";
+
+    private boolean convertToUpperCase = true;
+
+    public void setPasswordAttributeName(String passwordAttributeName) {
+        this.passwordAttributeName = passwordAttributeName;
+    }
+
+    public void setRoleAttributes(String[] roleAttributes) {
+        Assert.notNull(roleAttributes, "roleAttributes array cannot be null");
+        this.roleAttributes = roleAttributes;
+    }
+
+    public Object mapAttributes(String dn, Attributes attributes) throws NamingException {
+        LdapUserDetailsImpl.Essence essence = new LdapUserDetailsImpl.Essence();
+
+        essence.setDn(dn);
+        essence.setAttributes(attributes);
+
+        Attribute passwordAttribute = attributes.get(passwordAttributeName);
+
+        if(passwordAttribute != null) {
+            Object retrievedPassword = passwordAttribute.get();
+
+            if (!(retrievedPassword instanceof String)) {
+                // Assume it's binary
+                retrievedPassword = new String((byte[])retrievedPassword);
+            }
+
+            essence.setPassword((String)retrievedPassword);
+        }
+
+        // Map the roles
+
+        for(int i=0; roleAttributes != null && i < roleAttributes.length; i++) {
+            Attribute roleAttribute = attributes.get(roleAttributes[i]);
+
+            NamingEnumeration attributeRoles = roleAttribute.getAll();
+
+            while(attributeRoles.hasMore()) {
+                Object role = attributeRoles.next();
+
+                // We only handle Strings for the time being
+                if(role instanceof String) {
+                    if(convertToUpperCase) {
+                        role = ((String)role).toUpperCase();
+                    }
+
+                    essence.addAuthority(new GrantedAuthorityImpl(rolePrefix + role));
+                } else {
+                    logger.warn("Non-String value found for role attribute " + roleAttribute.getID());
+                }
+            }
+        }
+
+        return essence.createUserDetails();
+    }
+}