View Javadoc

1   package org.springframework.security.config;
2   
3   import org.springframework.beans.factory.xml.ParserContext;
4   import org.springframework.beans.factory.support.BeanDefinitionBuilder;
5   import org.springframework.beans.factory.support.RootBeanDefinition;
6   import org.springframework.beans.factory.config.RuntimeBeanReference;
7   import org.springframework.util.StringUtils;
8   
9   import org.w3c.dom.Element;
10  
11  /**
12   * @author Luke Taylor
13   * @version $Id: LdapUserServiceBeanDefinitionParser.java 3263 2008-08-26 13:51:01Z luke_t $
14   * @since 2.0
15   */
16  public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser {
17      public static final String ATT_SERVER = "server-ref";
18      public static final String ATT_USER_SEARCH_FILTER = "user-search-filter";
19      public static final String ATT_USER_SEARCH_BASE = "user-search-base";
20      public static final String DEF_USER_SEARCH_BASE = "";
21  
22      public static final String ATT_GROUP_SEARCH_FILTER = "group-search-filter";
23      public static final String ATT_GROUP_SEARCH_BASE = "group-search-base";
24      public static final String ATT_GROUP_ROLE_ATTRIBUTE = "group-role-attribute";
25      public static final String DEF_GROUP_SEARCH_FILTER = "(uniqueMember={0})";
26      public static final String DEF_GROUP_SEARCH_BASE = "";
27  
28      static final String ATT_ROLE_PREFIX = "role-prefix";
29      static final String ATT_USER_CLASS = "user-details-class";
30      static final String OPT_PERSON = "person";
31      static final String OPT_INETORGPERSON = "inetOrgPerson";
32  
33      public static final String LDAP_SEARCH_CLASS = "org.springframework.security.ldap.search.FilterBasedLdapUserSearch";
34      public static final String PERSON_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.PersonContextMapper";
35      public static final String INET_ORG_PERSON_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.InetOrgPersonContextMapper";
36      public static final String LDAP_USER_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.LdapUserDetailsMapper";
37      public static final String LDAP_AUTHORITIES_POPULATOR_CLASS = "org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator";
38  
39      protected String getBeanClassName(Element element) {
40          return "org.springframework.security.userdetails.ldap.LdapUserDetailsService";
41      }
42  
43      protected void doParse(Element elt, ParserContext parserContext, BeanDefinitionBuilder builder) {
44  
45          if (!StringUtils.hasText(elt.getAttribute(ATT_USER_SEARCH_FILTER))) {
46              parserContext.getReaderContext().error("User search filter must be supplied", elt);
47          }
48  
49          builder.addConstructorArg(parseSearchBean(elt, parserContext));
50          builder.addConstructorArg(parseAuthoritiesPopulator(elt, parserContext));
51          builder.addPropertyValue("userDetailsMapper", parseUserDetailsClass(elt, parserContext));
52      }
53  
54      static RootBeanDefinition parseSearchBean(Element elt, ParserContext parserContext) {
55          String userSearchFilter = elt.getAttribute(ATT_USER_SEARCH_FILTER);
56          String userSearchBase = elt.getAttribute(ATT_USER_SEARCH_BASE);
57          Object source = parserContext.extractSource(elt);
58  
59          if (StringUtils.hasText(userSearchBase)) {
60              if(!StringUtils.hasText(userSearchFilter)) {
61                  parserContext.getReaderContext().error(ATT_USER_SEARCH_BASE + " cannot be used without a " + ATT_USER_SEARCH_FILTER, source);
62              }
63          } else {
64              userSearchBase = DEF_USER_SEARCH_BASE;
65          }
66  
67          if (!StringUtils.hasText(userSearchFilter)) {
68              return null;
69          }
70  
71          BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(LDAP_SEARCH_CLASS);
72          searchBuilder.setSource(source);
73          searchBuilder.addConstructorArg(userSearchBase);
74          searchBuilder.addConstructorArg(userSearchFilter);
75          searchBuilder.addConstructorArg(parseServerReference(elt, parserContext));
76  
77          return (RootBeanDefinition) searchBuilder.getBeanDefinition();
78      }
79  
80      static RuntimeBeanReference parseServerReference(Element elt, ParserContext parserContext) {
81          String server = elt.getAttribute(ATT_SERVER);
82          boolean requiresDefaultName = false;
83  
84          if (!StringUtils.hasText(server)) {
85              server = BeanIds.CONTEXT_SOURCE;
86              requiresDefaultName = true;
87          }
88  
89          RuntimeBeanReference contextSource = new RuntimeBeanReference(server);
90          contextSource.setSource(parserContext.extractSource(elt));
91          LdapConfigUtils.registerPostProcessorIfNecessary(parserContext.getRegistry(), requiresDefaultName);
92  
93          return contextSource;
94      }
95  
96      static RootBeanDefinition parseUserDetailsClass(Element elt, ParserContext parserContext) {
97          String userDetailsClass = elt.getAttribute(ATT_USER_CLASS);
98  
99          if (OPT_PERSON.equals(userDetailsClass)) {
100             return new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null);
101         } else if (OPT_INETORGPERSON.equals(userDetailsClass)) {
102             return new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null);
103         }
104         return new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null);
105     }
106 
107     static RootBeanDefinition parseAuthoritiesPopulator(Element elt, ParserContext parserContext) {
108         String groupSearchFilter = elt.getAttribute(ATT_GROUP_SEARCH_FILTER);
109         String groupSearchBase = elt.getAttribute(ATT_GROUP_SEARCH_BASE);
110         String groupRoleAttribute = elt.getAttribute(ATT_GROUP_ROLE_ATTRIBUTE);
111         String rolePrefix = elt.getAttribute(ATT_ROLE_PREFIX);
112 
113         if (!StringUtils.hasText(groupSearchFilter)) {
114             groupSearchFilter = DEF_GROUP_SEARCH_FILTER;
115         }
116 
117         if (!StringUtils.hasText(groupSearchBase)) {
118             groupSearchBase = DEF_GROUP_SEARCH_BASE;
119         }
120 
121         BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(LDAP_AUTHORITIES_POPULATOR_CLASS);
122         populator.setSource(parserContext.extractSource(elt));
123         populator.addConstructorArg(parseServerReference(elt, parserContext));
124         populator.addConstructorArg(groupSearchBase);
125         populator.addPropertyValue("groupSearchFilter", groupSearchFilter);
126         populator.addPropertyValue("searchSubtree", Boolean.TRUE);
127 
128         if (StringUtils.hasText(rolePrefix)) {
129             if ("none".equals(rolePrefix)) {
130                 rolePrefix = "";
131             }
132             populator.addPropertyValue("rolePrefix", rolePrefix);
133         }
134 
135         if (StringUtils.hasLength(groupRoleAttribute)) {
136             populator.addPropertyValue("groupRoleAttribute", groupRoleAttribute);
137         }
138 
139         return (RootBeanDefinition) populator.getBeanDefinition();
140     }
141 }