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.springframework.security.providers.ldap.authenticator;
17  
18  import org.springframework.security.SpringSecurityMessageSource;
19  import org.springframework.security.ldap.LdapUserSearch;
20  import org.springframework.security.providers.ldap.LdapAuthenticator;
21  import org.springframework.beans.factory.InitializingBean;
22  import org.springframework.context.MessageSource;
23  import org.springframework.context.MessageSourceAware;
24  import org.springframework.context.support.MessageSourceAccessor;
25  import org.springframework.ldap.core.ContextSource;
26  import org.springframework.util.Assert;
27  
28  import java.text.MessageFormat;
29  import java.util.ArrayList;
30  import java.util.Collections;
31  import java.util.List;
32  
33  
34  /**
35   * Base class for the authenticator implementations.
36   *
37   * @author Luke Taylor
38   * @version $Id: AbstractLdapAuthenticator.java 2261 2007-11-20 20:54:48Z luke_t $
39   */
40  public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, InitializingBean, MessageSourceAware {
41      //~ Instance fields ================================================================================================
42  
43      private ContextSource contextSource;
44  
45      /** Optional search object which can be used to locate a user when a simple DN match isn't sufficient */
46      private LdapUserSearch userSearch;
47      protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
48  
49      /** The attributes which will be retrieved from the directory. Null means all attributes */
50      private String[] userAttributes = null;
51  
52      //private String[] userDnPattern = null;
53      /** Stores the patterns which are used as potential DN matches */
54      private MessageFormat[] userDnFormat = null;
55  
56      //~ Constructors ===================================================================================================
57  
58      /**
59       * Create an initialized instance with the {@link ContextSource} provided.
60       *
61       * @param contextSource
62       */
63      public AbstractLdapAuthenticator(ContextSource contextSource) {
64          Assert.notNull(contextSource, "contextSource must not be null.");
65          this.contextSource = contextSource;
66      }
67  
68      //~ Methods ========================================================================================================
69  
70      public void afterPropertiesSet() throws Exception {
71          Assert.isTrue((userDnFormat != null) || (userSearch != null),
72                  "Either an LdapUserSearch or DN pattern (or both) must be supplied.");
73      }
74  
75      protected ContextSource getContextSource() {
76          return contextSource;
77      }
78  
79      public String[] getUserAttributes() {
80          return userAttributes;
81      }
82  
83      /**
84       * Builds list of possible DNs for the user, worked out from the <tt>userDnPatterns</tt> property.
85       *
86       * @param username the user's login name
87       *
88       * @return the list of possible DN matches, empty if <tt>userDnPatterns</tt> wasn't set.
89       */
90      protected List getUserDns(String username) {
91          if (userDnFormat == null) {
92              return Collections.EMPTY_LIST;
93          }
94  
95          List userDns = new ArrayList(userDnFormat.length);
96          String[] args = new String[] {username};
97  
98          synchronized (userDnFormat) {
99              for (int i = 0; i < userDnFormat.length; i++) {
100                 userDns.add(userDnFormat[i].format(args));
101             }
102         }
103 
104         return userDns;
105     }
106 
107     protected LdapUserSearch getUserSearch() {
108         return userSearch;
109     }
110 
111     public void setMessageSource(MessageSource messageSource) {
112         Assert.notNull("Message source must not be null");
113         this.messages = new MessageSourceAccessor(messageSource);
114     }
115 
116     /**
117      * Sets the user attributes which will be retrieved from the directory.
118      *
119      * @param userAttributes
120      */
121     public void setUserAttributes(String[] userAttributes) {
122         Assert.notNull(userAttributes, "The userAttributes property cannot be set to null");
123         this.userAttributes = userAttributes;
124     }
125 
126     /**
127      * Sets the pattern which will be used to supply a DN for the user. The pattern should be the name relative
128      * to the root DN. The pattern argument {0} will contain the username. An example would be "cn={0},ou=people".
129      *
130      * @param dnPattern the array of patterns which will be tried when converting a username to a DN.
131      */
132     public void setUserDnPatterns(String[] dnPattern) {
133         Assert.notNull(dnPattern, "The array of DN patterns cannot be set to null");
134 //        this.userDnPattern = dnPattern;
135         userDnFormat = new MessageFormat[dnPattern.length];
136 
137         for (int i = 0; i < dnPattern.length; i++) {
138             userDnFormat[i] = new MessageFormat(dnPattern[i]);
139         }
140     }
141 
142     public void setUserSearch(LdapUserSearch userSearch) {
143         Assert.notNull(userSearch, "The userSearch cannot be set to null");
144         this.userSearch = userSearch;
145     }
146 }