View Javadoc

1   /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
2    *
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    *     http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  
16  package org.acegisecurity.userdetails.ldap;
17  
18  import org.acegisecurity.GrantedAuthorityImpl;
19  import org.acegisecurity.GrantedAuthority;
20  
21  import org.acegisecurity.ldap.LdapEntryMapper;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  
26  import org.springframework.util.Assert;
27  
28  import javax.naming.NamingEnumeration;
29  import javax.naming.NamingException;
30  import javax.naming.directory.Attribute;
31  import javax.naming.directory.Attributes;
32  
33  
34  /**
35   * The entry mapper used by the authenticators to create an ldap user object.
36   *
37   * @author Luke Taylor
38   * @version $Id$
39   */
40  public class LdapUserDetailsMapper implements LdapEntryMapper {
41      //~ Instance fields ================================================================================================
42  
43      private final Log logger = LogFactory.getLog(LdapUserDetailsMapper.class);
44      private String passwordAttributeName = "userPassword";
45      private String rolePrefix = "ROLE_";
46      private String[] roleAttributes = null;
47      private boolean convertToUpperCase = true;
48  
49      //~ Methods ========================================================================================================
50  
51      public Object mapAttributes(String dn, Attributes attributes)
52          throws NamingException {
53          LdapUserDetailsImpl.Essence essence = new LdapUserDetailsImpl.Essence();
54  
55          essence.setDn(dn);
56          essence.setAttributes(attributes);
57  
58          Attribute passwordAttribute = attributes.get(passwordAttributeName);
59  
60          if (passwordAttribute != null) {
61              essence.setPassword(mapPassword(passwordAttribute));
62          }
63  
64          // Map the roles
65          for (int i = 0; (roleAttributes != null) && (i < roleAttributes.length); i++) {
66              Attribute roleAttribute = attributes.get(roleAttributes[i]);
67  
68              if (roleAttribute == null) {
69                  logger.debug("Couldn't read role attribute '" + roleAttributes[i] + "' for user " + dn);
70                  continue;
71              }
72  
73              NamingEnumeration attributeRoles = roleAttribute.getAll();
74  
75              while (attributeRoles.hasMore()) {
76                  GrantedAuthority authority = createAuthority(attributeRoles.next());
77  
78                  if (authority != null) {
79                      essence.addAuthority(authority);
80                  } else {
81                      logger.debug("Failed to create an authority value from attribute with Id: "
82                              + roleAttribute.getID());
83                  }
84              }
85          }
86  
87          return essence;
88      }
89  
90      /**
91       * Extension point to allow customized creation of the user's password from
92       * the attribute stored in the directory.
93       *
94       * @param passwordAttribute the attribute instance containing the password
95       * @return a String representation of the password.
96       */
97      protected String mapPassword(Attribute passwordAttribute) throws NamingException {
98          Object retrievedPassword = passwordAttribute.get();
99  
100         if (!(retrievedPassword instanceof String)) {
101             // Assume it's binary
102             retrievedPassword = new String((byte[]) retrievedPassword);
103         }
104 
105         return (String) retrievedPassword;
106 
107     }
108 
109     /**
110      * Creates a GrantedAuthority from a role attribute. Override to customize
111      * authority object creation.
112      * <p>
113      * The default implementation converts string attributes to roles, making use of the <tt>rolePrefix</tt>
114      * and <tt>convertToUpperCase</tt> properties. Non-String attributes are ignored.
115      * </p>
116      *
117      * @param role the attribute returned from
118      * @return the authority to be added to the list of authorities for the user, or null
119      * if this attribute should be ignored.
120      */
121     protected GrantedAuthority createAuthority(Object role) {
122         if (role instanceof String) {
123             if (convertToUpperCase) {
124                 role = ((String) role).toUpperCase();
125             }
126             return new GrantedAuthorityImpl(rolePrefix + role);
127         }
128         return null;
129     }
130 
131     /**
132      * Determines whether role field values will be converted to upper case when loaded.
133      * The default is true.
134      *
135      * @param convertToUpperCase true if the roles should be converted to upper case.
136      */
137     public void setConvertToUpperCase(boolean convertToUpperCase) {
138         this.convertToUpperCase = convertToUpperCase;
139     }
140 
141     /**
142      * The name of the attribute which contains the user's password.
143      * Defaults to "userPassword".
144      *
145      * @param passwordAttributeName the name of the attribute
146      */
147     public void setPasswordAttributeName(String passwordAttributeName) {
148         this.passwordAttributeName = passwordAttributeName;
149     }
150 
151     /**
152      * The names of any attributes in the user's  entry which represent application
153      * roles. These will be converted to <tt>GrantedAuthority</tt>s and added to the
154      * list in the returned LdapUserDetails object.
155      *
156      * @param roleAttributes the names of the role attributes.
157      */
158     public void setRoleAttributes(String[] roleAttributes) {
159         Assert.notNull(roleAttributes, "roleAttributes array cannot be null");
160         this.roleAttributes = roleAttributes;
161     }
162 
163     /**
164      * The prefix that should be applied to the role names
165      * @param rolePrefix the prefix (defaults to "ROLE_").
166      */
167     public void setRolePrefix(String rolePrefix) {
168         this.rolePrefix = rolePrefix;
169     }
170 }