View Javadoc

1   package org.springframework.security.ldap;
2   
3   import org.springframework.security.BadCredentialsException;
4   import org.springframework.security.SpringSecurityMessageSource;
5   import org.springframework.context.MessageSource;
6   import org.springframework.context.MessageSourceAware;
7   import org.springframework.context.support.MessageSourceAccessor;
8   import org.springframework.ldap.core.support.LdapContextSource;
9   import org.springframework.util.Assert;
10  
11  import org.apache.commons.logging.Log;
12  import org.apache.commons.logging.LogFactory;
13  
14  import javax.naming.Context;
15  import javax.naming.directory.DirContext;
16  import java.util.ArrayList;
17  import java.util.Hashtable;
18  import java.util.StringTokenizer;
19  
20  /**
21   * SpringSecurityContextSource implementation which uses Spring LDAP's <tt>LdapContextSource</tt> as a base
22   * class. Intended as a replacement for <tt>DefaultInitialDirContextFactory</tt> from versions of the framework prior
23   * to 2.0.
24   *
25   * @author Luke Taylor
26   * @version $Id: DefaultSpringSecurityContextSource.java 2363 2007-12-11 18:08:44Z luke_t $
27   * @since 2.0
28   */
29  public class DefaultSpringSecurityContextSource extends LdapContextSource implements SpringSecurityContextSource,
30          MessageSourceAware {
31  
32      private static final Log logger = LogFactory.getLog(DefaultSpringSecurityContextSource.class);
33      private String rootDn;
34  
35      protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
36  
37      /**
38       * Create and initialize an instance which will connect to the supplied LDAP URL.
39       *
40       * @param providerUrl an LDAP URL of the form <code>ldap://localhost:389/base_dn<code>
41       */
42      public DefaultSpringSecurityContextSource(String providerUrl) {
43          Assert.hasLength(providerUrl, "An LDAP connection URL must be supplied.");
44  
45          StringTokenizer st = new StringTokenizer(providerUrl);
46  
47          ArrayList urls = new ArrayList();
48  
49          // Work out rootDn from the first URL and check that the other URLs (if any) match
50          while (st.hasMoreTokens()) {
51              String url = st.nextToken();
52              String urlRootDn = LdapUtils.parseRootDnFromUrl(url);
53  
54              urls.add(url.substring(0, url.lastIndexOf(urlRootDn)));
55  
56              logger.info(" URL '" + url + "', root DN is '" + urlRootDn + "'");
57  
58              if (rootDn == null) {
59                  rootDn = urlRootDn;
60              } else if (!rootDn.equals(urlRootDn)) {
61                  throw new IllegalArgumentException("Root DNs must be the same when using multiple URLs");
62              }
63          }
64  
65          super.setUrls((String[]) urls.toArray(new String[urls.size()]));
66          super.setBase(rootDn);
67      }
68  
69      public DirContext getReadWriteContext(String userDn, Object credentials) {
70          Hashtable env = new Hashtable(getAnonymousEnv());
71  
72          env.put(Context.SECURITY_PRINCIPAL, userDn);
73          env.put(Context.SECURITY_CREDENTIALS, credentials);
74  
75          if (logger.isDebugEnabled()) {
76              logger.debug("Creating context with principal: '" + userDn + "'");
77          }
78  
79          try {
80              return createContext(env);
81          } catch (org.springframework.ldap.NamingException e) {
82              if ((e instanceof org.springframework.ldap.AuthenticationException)
83                      || (e instanceof org.springframework.ldap.OperationNotSupportedException)) {
84                  throw new BadCredentialsException(
85                          messages.getMessage("DefaultSpringSecurityContextSource.badCredentials", "Bad credentials"), e);
86              }
87              throw e;
88          }
89      }
90  
91      public void setMessageSource(MessageSource messageSource) {
92          this.messages = new MessageSourceAccessor(messageSource);
93      }
94  }