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.providers.ldap.authenticator;
017:
018: import org.acegisecurity.AcegiMessageSource;
019:
020: import org.acegisecurity.ldap.InitialDirContextFactory;
021: import org.acegisecurity.ldap.LdapEntryMapper;
022: import org.acegisecurity.ldap.LdapUserSearch;
023:
024: import org.acegisecurity.providers.ldap.LdapAuthenticator;
025:
026: import org.acegisecurity.userdetails.ldap.LdapUserDetailsMapper;
027:
028: import org.springframework.beans.factory.InitializingBean;
029:
030: import org.springframework.context.MessageSource;
031: import org.springframework.context.MessageSourceAware;
032: import org.springframework.context.support.MessageSourceAccessor;
033:
034: import org.springframework.util.Assert;
035:
036: import java.text.MessageFormat;
037:
038: import java.util.ArrayList;
039: import java.util.List;
040:
041: /**
042: * Base class for the authenticator implementations.
043: *
044: * @author Luke Taylor
045: * @version $Id: AbstractLdapAuthenticator.java 1585 2006-07-20 13:15:55Z carlossg $
046: */
047: public abstract class AbstractLdapAuthenticator implements
048: LdapAuthenticator, InitializingBean, MessageSourceAware {
049: //~ Instance fields ================================================================================================
050:
051: private InitialDirContextFactory initialDirContextFactory;
052: private LdapUserDetailsMapper userDetailsMapper = new LdapUserDetailsMapper();
053:
054: /** Optional search object which can be used to locate a user when a simple DN match isn't sufficient */
055: private LdapUserSearch userSearch;
056: protected MessageSourceAccessor messages = AcegiMessageSource
057: .getAccessor();
058:
059: /**
060: * The suffix to be added to the DN patterns, worked out internally from the root DN of the configured
061: * InitialDirContextFactory.
062: */
063: private String dnSuffix = "";
064:
065: /** The attributes which will be retrieved from the directory. Null means all attributes */
066: private String[] userAttributes = null;
067:
068: //private String[] userDnPattern = null;
069: /** Stores the patterns which are used as potential DN matches */
070: private MessageFormat[] userDnFormat = null;
071:
072: //~ Constructors ===================================================================================================
073:
074: /**
075: * Create an initialized instance to the {@link InitialDirContextFactory} provided.
076: *
077: * @param initialDirContextFactory
078: */
079: public AbstractLdapAuthenticator(
080: InitialDirContextFactory initialDirContextFactory) {
081: this .setInitialDirContextFactory(initialDirContextFactory);
082: }
083:
084: // ~ Methods
085: // ========================================================================================================
086:
087: public void afterPropertiesSet() throws Exception {
088: Assert
089: .isTrue((userDnFormat != null) || (userSearch != null),
090: "Either an LdapUserSearch or DN pattern (or both) must be supplied.");
091: }
092:
093: /**
094: * Set the {@link InitialDirContextFactory} and initialize this instance from its data.
095: *
096: * @param initialDirContextFactory
097: */
098: private void setInitialDirContextFactory(
099: InitialDirContextFactory initialDirContextFactory) {
100: Assert.notNull(initialDirContextFactory,
101: "initialDirContextFactory must not be null.");
102: this .initialDirContextFactory = initialDirContextFactory;
103:
104: String rootDn = initialDirContextFactory.getRootDn();
105:
106: if (rootDn.length() > 0) {
107: dnSuffix = "," + rootDn;
108: }
109: }
110:
111: protected InitialDirContextFactory getInitialDirContextFactory() {
112: return initialDirContextFactory;
113: }
114:
115: public String[] getUserAttributes() {
116: return userAttributes;
117: }
118:
119: protected LdapEntryMapper getUserDetailsMapper() {
120: return userDetailsMapper;
121: }
122:
123: /**
124: * Builds list of possible DNs for the user, worked out from the <tt>userDnPatterns</tt> property. The
125: * returned value includes the root DN of the provider URL used to configure the
126: * <tt>InitialDirContextfactory</tt>.
127: *
128: * @param username the user's login name
129: *
130: * @return the list of possible DN matches, empty if <tt>userDnPatterns</tt> wasn't set.
131: */
132: protected List getUserDns(String username) {
133: if (userDnFormat == null) {
134: return new ArrayList(0);
135: }
136:
137: List userDns = new ArrayList(userDnFormat.length);
138: String[] args = new String[] { username };
139:
140: synchronized (userDnFormat) {
141: for (int i = 0; i < userDnFormat.length; i++) {
142: userDns.add(userDnFormat[i].format(args) + dnSuffix);
143: }
144: }
145:
146: return userDns;
147: }
148:
149: protected LdapUserSearch getUserSearch() {
150: return userSearch;
151: }
152:
153: public void setMessageSource(MessageSource messageSource) {
154: Assert.notNull("Message source must not be null");
155: this .messages = new MessageSourceAccessor(messageSource);
156: }
157:
158: /**
159: * Sets the user attributes which will be retrieved from the directory.
160: *
161: * @param userAttributes
162: */
163: public void setUserAttributes(String[] userAttributes) {
164: Assert.notNull(userAttributes,
165: "The userAttributes property cannot be set to null");
166: this .userAttributes = userAttributes;
167: }
168:
169: public void setUserDetailsMapper(
170: LdapUserDetailsMapper userDetailsMapper) {
171: Assert.notNull("userDetailsMapper must not be null");
172: this .userDetailsMapper = userDetailsMapper;
173: }
174:
175: /**
176: * Sets the pattern which will be used to supply a DN for the user. The pattern should be the name relative
177: * to the root DN. The pattern argument {0} will contain the username. An example would be "cn={0},ou=people".
178: *
179: * @param dnPattern the array of patterns which will be tried when obtaining a username
180: * to a DN.
181: */
182: public void setUserDnPatterns(String[] dnPattern) {
183: Assert.notNull(dnPattern,
184: "The array of DN patterns cannot be set to null");
185: // this.userDnPattern = dnPattern;
186: userDnFormat = new MessageFormat[dnPattern.length];
187:
188: for (int i = 0; i < dnPattern.length; i++) {
189: userDnFormat[i] = new MessageFormat(dnPattern[i]);
190: }
191: }
192:
193: public void setUserSearch(LdapUserSearch userSearch) {
194: Assert.notNull(userSearch,
195: "The userSearch cannot be set to null");
196: this.userSearch = userSearch;
197: }
198: }
|