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 }