001: /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
002: *
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015:
016: package org.acegisecurity.userdetails.ldap;
017:
018: import org.acegisecurity.GrantedAuthorityImpl;
019: import org.acegisecurity.GrantedAuthority;
020:
021: import org.acegisecurity.ldap.LdapEntryMapper;
022:
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025:
026: import org.springframework.util.Assert;
027:
028: import javax.naming.NamingEnumeration;
029: import javax.naming.NamingException;
030: import javax.naming.directory.Attribute;
031: import javax.naming.directory.Attributes;
032:
033: /**
034: * The entry mapper used by the authenticators to create an ldap user object.
035: *
036: * @author Luke Taylor
037: * @version $Id$
038: */
039: public class LdapUserDetailsMapper implements LdapEntryMapper {
040: //~ Instance fields ================================================================================================
041:
042: private final Log logger = LogFactory
043: .getLog(LdapUserDetailsMapper.class);
044: private String passwordAttributeName = "userPassword";
045: private String rolePrefix = "ROLE_";
046: private String[] roleAttributes = null;
047: private boolean convertToUpperCase = true;
048:
049: //~ Methods ========================================================================================================
050:
051: public Object mapAttributes(String dn, Attributes attributes)
052: throws NamingException {
053: LdapUserDetailsImpl.Essence essence = new LdapUserDetailsImpl.Essence();
054:
055: essence.setDn(dn);
056: essence.setAttributes(attributes);
057:
058: Attribute passwordAttribute = attributes
059: .get(passwordAttributeName);
060:
061: if (passwordAttribute != null) {
062: essence.setPassword(mapPassword(passwordAttribute));
063: }
064:
065: // Map the roles
066: for (int i = 0; (roleAttributes != null)
067: && (i < roleAttributes.length); i++) {
068: Attribute roleAttribute = attributes.get(roleAttributes[i]);
069:
070: if (roleAttribute == null) {
071: logger.debug("Couldn't read role attribute '"
072: + roleAttributes[i] + "' for user " + dn);
073: continue;
074: }
075:
076: NamingEnumeration attributeRoles = roleAttribute.getAll();
077:
078: while (attributeRoles.hasMore()) {
079: GrantedAuthority authority = createAuthority(attributeRoles
080: .next());
081:
082: if (authority != null) {
083: essence.addAuthority(authority);
084: } else {
085: logger
086: .debug("Failed to create an authority value from attribute with Id: "
087: + roleAttribute.getID());
088: }
089: }
090: }
091:
092: return essence;
093: }
094:
095: /**
096: * Extension point to allow customized creation of the user's password from
097: * the attribute stored in the directory.
098: *
099: * @param passwordAttribute the attribute instance containing the password
100: * @return a String representation of the password.
101: */
102: protected String mapPassword(Attribute passwordAttribute)
103: throws NamingException {
104: Object retrievedPassword = passwordAttribute.get();
105:
106: if (!(retrievedPassword instanceof String)) {
107: // Assume it's binary
108: retrievedPassword = new String((byte[]) retrievedPassword);
109: }
110:
111: return (String) retrievedPassword;
112:
113: }
114:
115: /**
116: * Creates a GrantedAuthority from a role attribute. Override to customize
117: * authority object creation.
118: * <p>
119: * The default implementation converts string attributes to roles, making use of the <tt>rolePrefix</tt>
120: * and <tt>convertToUpperCase</tt> properties. Non-String attributes are ignored.
121: * </p>
122: *
123: * @param role the attribute returned from
124: * @return the authority to be added to the list of authorities for the user, or null
125: * if this attribute should be ignored.
126: */
127: protected GrantedAuthority createAuthority(Object role) {
128: if (role instanceof String) {
129: if (convertToUpperCase) {
130: role = ((String) role).toUpperCase();
131: }
132: return new GrantedAuthorityImpl(rolePrefix + role);
133: }
134: return null;
135: }
136:
137: /**
138: * Determines whether role field values will be converted to upper case when loaded.
139: * The default is true.
140: *
141: * @param convertToUpperCase true if the roles should be converted to upper case.
142: */
143: public void setConvertToUpperCase(boolean convertToUpperCase) {
144: this .convertToUpperCase = convertToUpperCase;
145: }
146:
147: /**
148: * The name of the attribute which contains the user's password.
149: * Defaults to "userPassword".
150: *
151: * @param passwordAttributeName the name of the attribute
152: */
153: public void setPasswordAttributeName(String passwordAttributeName) {
154: this .passwordAttributeName = passwordAttributeName;
155: }
156:
157: /**
158: * The names of any attributes in the user's entry which represent application
159: * roles. These will be converted to <tt>GrantedAuthority</tt>s and added to the
160: * list in the returned LdapUserDetails object.
161: *
162: * @param roleAttributes the names of the role attributes.
163: */
164: public void setRoleAttributes(String[] roleAttributes) {
165: Assert.notNull(roleAttributes,
166: "roleAttributes array cannot be null");
167: this .roleAttributes = roleAttributes;
168: }
169:
170: /**
171: * The prefix that should be applied to the role names
172: * @param rolePrefix the prefix (defaults to "ROLE_").
173: */
174: public void setRolePrefix(String rolePrefix) {
175: this.rolePrefix = rolePrefix;
176: }
177: }
|