View Javadoc

1   package org.springframework.security.config;
2   
3   import org.springframework.beans.factory.config.BeanDefinition;
4   import org.springframework.beans.factory.config.RuntimeBeanReference;
5   import org.springframework.beans.factory.support.BeanDefinitionBuilder;
6   import org.springframework.beans.factory.support.RootBeanDefinition;
7   import org.springframework.beans.factory.xml.BeanDefinitionParser;
8   import org.springframework.beans.factory.xml.ParserContext;
9   import org.springframework.util.StringUtils;
10  import org.springframework.util.xml.DomUtils;
11  
12  import org.apache.commons.logging.Log;
13  import org.apache.commons.logging.LogFactory;
14  import org.w3c.dom.Element;
15  
16  /**
17   * Ldap authentication provider namespace configuration.
18   *
19   * @author Luke Taylor
20   * @version $Id: LdapProviderBeanDefinitionParser.java 3194 2008-07-30 11:01:23Z luke_t $
21   * @since 2.0
22   */
23  public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
24      private Log logger = LogFactory.getLog(getClass());
25    
26      private static final String ATT_USER_DN_PATTERN = "user-dn-pattern";
27      private static final String ATT_USER_PASSWORD = "password-attribute";
28      private static final String ATT_HASH = PasswordEncoderParser.ATT_HASH; 
29      
30      private static final String DEF_USER_SEARCH_FILTER = "uid={0}";
31      
32      private static final String PROVIDER_CLASS = "org.springframework.security.providers.ldap.LdapAuthenticationProvider";
33      private static final String BIND_AUTH_CLASS = "org.springframework.security.providers.ldap.authenticator.BindAuthenticator";
34      private static final String PASSWD_AUTH_CLASS = "org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator";
35  
36      public BeanDefinition parse(Element elt, ParserContext parserContext) {
37          RuntimeBeanReference contextSource = LdapUserServiceBeanDefinitionParser.parseServerReference(elt, parserContext);
38          
39          BeanDefinition searchBean = LdapUserServiceBeanDefinitionParser.parseSearchBean(elt, parserContext);
40          String userDnPattern = elt.getAttribute(ATT_USER_DN_PATTERN);
41          
42          String[] userDnPatternArray = new String[0];
43          
44          if (StringUtils.hasText(userDnPattern)) {
45              userDnPatternArray = new String[] {userDnPattern};
46              // TODO: Validate the pattern and make sure it is a valid DN.
47          } else if (searchBean == null) {
48              logger.info("No search information or DN pattern specified. Using default search filter '" + DEF_USER_SEARCH_FILTER + "'");
49              BeanDefinitionBuilder searchBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(LdapUserServiceBeanDefinitionParser.LDAP_SEARCH_CLASS); 
50              searchBeanBuilder.setSource(elt);
51              searchBeanBuilder.addConstructorArg("");
52              searchBeanBuilder.addConstructorArg(DEF_USER_SEARCH_FILTER);
53              searchBeanBuilder.addConstructorArg(contextSource);
54              searchBean = searchBeanBuilder.getBeanDefinition();
55          }
56          
57          BeanDefinitionBuilder authenticatorBuilder = 
58              BeanDefinitionBuilder.rootBeanDefinition(BIND_AUTH_CLASS);
59          Element passwordCompareElt = DomUtils.getChildElementByTagName(elt, Elements.LDAP_PASSWORD_COMPARE);
60          
61          if (passwordCompareElt != null) {
62              authenticatorBuilder = 
63                  BeanDefinitionBuilder.rootBeanDefinition(PASSWD_AUTH_CLASS);
64              
65              String passwordAttribute = passwordCompareElt.getAttribute(ATT_USER_PASSWORD);
66              if (StringUtils.hasText(passwordAttribute)) {
67                  authenticatorBuilder.addPropertyValue("passwordAttributeName", passwordAttribute);
68              }
69              
70              Element passwordEncoderElement = DomUtils.getChildElementByTagName(passwordCompareElt, Elements.PASSWORD_ENCODER);
71              String hash = passwordCompareElt.getAttribute(ATT_HASH);
72              
73              if (passwordEncoderElement != null) {
74                  if (StringUtils.hasText(hash)) {
75                      parserContext.getReaderContext().warning("Attribute 'hash' cannot be used with 'password-encoder' and " +
76                              "will be ignored.", parserContext.extractSource(elt));
77                  }
78                  PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElement, parserContext);
79                  authenticatorBuilder.addPropertyValue("passwordEncoder", pep.getPasswordEncoder());
80                  
81                  if (pep.getSaltSource() != null) {
82                      parserContext.getReaderContext().warning("Salt source information isn't valid when used with LDAP", 
83                              passwordEncoderElement);
84                  }
85              } else if (StringUtils.hasText(hash)) {
86                  Class encoderClass = (Class) PasswordEncoderParser.ENCODER_CLASSES.get(hash);
87                  authenticatorBuilder.addPropertyValue("passwordEncoder", new RootBeanDefinition(encoderClass));
88              }
89          }
90          
91          authenticatorBuilder.addConstructorArg(contextSource);
92          authenticatorBuilder.addPropertyValue("userDnPatterns", userDnPatternArray);
93          
94          if (searchBean != null) {
95              authenticatorBuilder.addPropertyValue("userSearch", searchBean);
96          }
97                  
98          BeanDefinitionBuilder ldapProvider = BeanDefinitionBuilder.rootBeanDefinition(PROVIDER_CLASS);
99          ldapProvider.addConstructorArg(authenticatorBuilder.getBeanDefinition());
100         ldapProvider.addConstructorArg(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext));
101         ldapProvider.addPropertyValue("userDetailsContextMapper", 
102                 LdapUserServiceBeanDefinitionParser.parseUserDetailsClass(elt, parserContext));
103         parserContext.getRegistry().registerBeanDefinition(BeanIds.LDAP_AUTHENTICATION_PROVIDER, ldapProvider.getBeanDefinition());
104         
105         ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.LDAP_AUTHENTICATION_PROVIDER);
106 
107         return null;
108     }
109 }