1 package org.springframework.security.config;
2
3 import org.springframework.beans.BeansException;
4 import org.springframework.beans.PropertyValue;
5 import org.springframework.beans.factory.config.BeanDefinition;
6 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
7 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
8 import org.springframework.beans.factory.config.RuntimeBeanReference;
9 import org.springframework.beans.factory.parsing.BeanComponentDefinition;
10 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
11 import org.springframework.beans.factory.support.RootBeanDefinition;
12 import org.springframework.beans.factory.xml.BeanDefinitionParser;
13 import org.springframework.beans.factory.xml.ParserContext;
14 import org.springframework.core.Ordered;
15 import org.springframework.security.providers.dao.DaoAuthenticationProvider;
16 import org.springframework.util.StringUtils;
17 import org.springframework.util.xml.DomUtils;
18 import org.w3c.dom.Element;
19
20
21
22
23
24
25
26
27 class AuthenticationProviderBeanDefinitionParser implements BeanDefinitionParser {
28 private static String ATT_USER_DETAILS_REF = "user-service-ref";
29
30 public BeanDefinition parse(Element element, ParserContext parserContext) {
31 RootBeanDefinition authProvider = new RootBeanDefinition(DaoAuthenticationProvider.class);
32 authProvider.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
33 authProvider.setSource(parserContext.extractSource(element));
34
35 Element passwordEncoderElt = DomUtils.getChildElementByTagName(element, Elements.PASSWORD_ENCODER);
36
37 if (passwordEncoderElt != null) {
38 PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElt, parserContext);
39 authProvider.getPropertyValues().addPropertyValue("passwordEncoder", pep.getPasswordEncoder());
40
41 if (pep.getSaltSource() != null) {
42 authProvider.getPropertyValues().addPropertyValue("saltSource", pep.getSaltSource());
43 }
44 }
45
46 Element userServiceElt = DomUtils.getChildElementByTagName(element, Elements.USER_SERVICE);
47 Element jdbcUserServiceElt = DomUtils.getChildElementByTagName(element, Elements.JDBC_USER_SERVICE);
48 Element ldapUserServiceElt = DomUtils.getChildElementByTagName(element, Elements.LDAP_USER_SERVICE);
49
50
51 final String id = parserContext.getReaderContext().generateBeanName(authProvider);
52 parserContext.getRegistry().registerBeanDefinition(id, authProvider);
53 parserContext.registerComponent(new BeanComponentDefinition(authProvider, id));
54
55 String ref = element.getAttribute(ATT_USER_DETAILS_REF);
56
57 if (StringUtils.hasText(ref)) {
58 if (userServiceElt != null || jdbcUserServiceElt != null || ldapUserServiceElt != null) {
59 parserContext.getReaderContext().error("The " + ATT_USER_DETAILS_REF + " attribute cannot be used in combination with child" +
60 "elements '" + Elements.USER_SERVICE + "', '" + Elements.JDBC_USER_SERVICE + "' or '" +
61 Elements.LDAP_USER_SERVICE + "'", element);
62 }
63 } else {
64
65 AbstractUserDetailsServiceBeanDefinitionParser parser = null;
66 Element elt = null;
67
68 if (userServiceElt != null) {
69 elt = userServiceElt;
70 parser = new UserServiceBeanDefinitionParser();
71 } else if (jdbcUserServiceElt != null) {
72 elt = jdbcUserServiceElt;
73 parser = new JdbcUserServiceBeanDefinitionParser();
74 } else if (ldapUserServiceElt != null) {
75 elt = ldapUserServiceElt;
76 parser = new LdapUserServiceBeanDefinitionParser();
77 } else {
78 parserContext.getReaderContext().error("A user-service is required", element);
79 }
80
81 parser.parse(elt, parserContext);
82 ref = parser.getId();
83 }
84
85 authProvider.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(ref));
86
87 BeanDefinitionBuilder cacheResolverBldr = BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProviderCacheResolver.class);
88 cacheResolverBldr.addConstructorArg(id);
89 cacheResolverBldr.addConstructorArg(ref);
90 cacheResolverBldr.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
91 BeanDefinition cacheResolver = cacheResolverBldr.getBeanDefinition();
92
93 String name = parserContext.getReaderContext().generateBeanName(cacheResolver);
94 parserContext.getRegistry().registerBeanDefinition(name , cacheResolver);
95 parserContext.registerComponent(new BeanComponentDefinition(cacheResolver, name));
96
97 ConfigUtils.addAuthenticationProvider(parserContext, id);
98
99 return null;
100 }
101
102
103
104
105
106 static class AuthenticationProviderCacheResolver implements BeanFactoryPostProcessor, Ordered {
107 private String providerId;
108 private String userServiceId;
109
110 public AuthenticationProviderCacheResolver(String providerId, String userServiceId) {
111 this.providerId = providerId;
112 this.userServiceId = userServiceId;
113 }
114
115 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
116 RootBeanDefinition provider = (RootBeanDefinition) beanFactory.getBeanDefinition(providerId);
117
118 String cachingId = userServiceId + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
119
120 if (beanFactory.containsBeanDefinition(cachingId)) {
121 RootBeanDefinition cachingUserService = (RootBeanDefinition) beanFactory.getBeanDefinition(cachingId);
122
123 PropertyValue userCacheProperty = cachingUserService.getPropertyValues().getPropertyValue("userCache");
124
125 provider.getPropertyValues().addPropertyValue(userCacheProperty);
126 }
127 }
128
129 public int getOrder() {
130 return HIGHEST_PRECEDENCE;
131 }
132 }
133 }