1 package org.springframework.security.config;
2
3 import org.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
5 import org.springframework.beans.factory.config.BeanDefinition;
6 import org.springframework.beans.factory.config.RuntimeBeanReference;
7 import org.springframework.beans.factory.support.ManagedList;
8 import org.springframework.beans.factory.support.RootBeanDefinition;
9 import org.springframework.beans.factory.xml.BeanDefinitionParser;
10 import org.springframework.beans.factory.xml.ParserContext;
11 import org.springframework.security.ui.rememberme.JdbcTokenRepositoryImpl;
12 import org.springframework.security.ui.rememberme.PersistentTokenBasedRememberMeServices;
13 import org.springframework.security.ui.rememberme.RememberMeProcessingFilter;
14 import org.springframework.security.ui.rememberme.TokenBasedRememberMeServices;
15 import org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider;
16 import org.springframework.util.StringUtils;
17 import org.w3c.dom.Element;
18
19
20
21
22
23
24 public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
25 static final String ATT_KEY = "key";
26 static final String DEF_KEY = "SpringSecured";
27
28 static final String ATT_DATA_SOURCE = "data-source-ref";
29 static final String ATT_SERVICES_REF = "services-ref";
30 static final String ATT_TOKEN_REPOSITORY = "token-repository-ref";
31 static final String ATT_USER_SERVICE_REF = "user-service-ref";
32 static final String ATT_TOKEN_VALIDITY = "token-validity-seconds";
33
34 protected final Log logger = LogFactory.getLog(getClass());
35 private String servicesName;
36
37 public BeanDefinition parse(Element element, ParserContext parserContext) {
38 String tokenRepository = null;
39 String dataSource = null;
40 String key = null;
41 Object source = null;
42 String userServiceRef = null;
43 String rememberMeServicesRef = null;
44 String tokenValiditySeconds = null;
45
46 if (element != null) {
47 tokenRepository = element.getAttribute(ATT_TOKEN_REPOSITORY);
48 dataSource = element.getAttribute(ATT_DATA_SOURCE);
49 key = element.getAttribute(ATT_KEY);
50 userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
51 rememberMeServicesRef = element.getAttribute(ATT_SERVICES_REF);
52 tokenValiditySeconds = element.getAttribute(ATT_TOKEN_VALIDITY);
53 source = parserContext.extractSource(element);
54 }
55
56 if (!StringUtils.hasText(key)) {
57 key = DEF_KEY;
58 }
59
60 RootBeanDefinition services = null;
61
62 boolean dataSourceSet = StringUtils.hasText(dataSource);
63 boolean tokenRepoSet = StringUtils.hasText(tokenRepository);
64 boolean servicesRefSet = StringUtils.hasText(rememberMeServicesRef);
65 boolean userServiceSet = StringUtils.hasText(userServiceRef);
66 boolean tokenValiditySet = StringUtils.hasText(tokenValiditySeconds);
67
68 if (servicesRefSet && (dataSourceSet || tokenRepoSet || userServiceSet || tokenValiditySet)) {
69 parserContext.getReaderContext().error(ATT_SERVICES_REF + " can't be used in combination with attributes "
70 + ATT_TOKEN_REPOSITORY + "," + ATT_DATA_SOURCE + ", " + ATT_USER_SERVICE_REF + " or " + ATT_TOKEN_VALIDITY, source);
71 }
72
73 if (dataSourceSet && tokenRepoSet) {
74 parserContext.getReaderContext().error("Specify " + ATT_TOKEN_REPOSITORY + " or " +
75 ATT_DATA_SOURCE +" but not both", source);
76 }
77
78 boolean isPersistent = dataSourceSet | tokenRepoSet;
79
80 if (isPersistent) {
81 Object tokenRepo;
82 services = new RootBeanDefinition(PersistentTokenBasedRememberMeServices.class);
83
84 if (tokenRepoSet) {
85 tokenRepo = new RuntimeBeanReference(tokenRepository);
86 } else {
87 tokenRepo = new RootBeanDefinition(JdbcTokenRepositoryImpl.class);
88 ((BeanDefinition)tokenRepo).getPropertyValues().addPropertyValue("dataSource",
89 new RuntimeBeanReference(dataSource));
90 }
91 services.getPropertyValues().addPropertyValue("tokenRepository", tokenRepo);
92 } else if (!servicesRefSet) {
93 services = new RootBeanDefinition(TokenBasedRememberMeServices.class);
94 }
95
96 if (services != null) {
97 if (userServiceSet) {
98 services.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef));
99 }
100
101 if (tokenValiditySet) {
102 services.getPropertyValues().addPropertyValue("tokenValiditySeconds", new Integer(tokenValiditySeconds));
103 }
104 services.setSource(source);
105 services.getPropertyValues().addPropertyValue(ATT_KEY, key);
106 parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services);
107 servicesName = BeanIds.REMEMBER_ME_SERVICES;
108 } else {
109 servicesName = rememberMeServicesRef;
110 parserContext.getRegistry().registerAlias(rememberMeServicesRef, BeanIds.REMEMBER_ME_SERVICES);
111 }
112
113 registerProvider(parserContext, source, key);
114
115 registerFilter(parserContext, source);
116
117 return null;
118 }
119
120 String getServicesName() {
121 return servicesName;
122 }
123
124 private void registerProvider(ParserContext pc, Object source, String key) {
125
126 RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class);
127 provider.setSource(source);
128 provider.getPropertyValues().addPropertyValue(ATT_KEY, key);
129 pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER, provider);
130 ConfigUtils.addAuthenticationProvider(pc, BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER);
131 }
132
133 private void registerFilter(ParserContext pc, Object source) {
134 RootBeanDefinition filter = new RootBeanDefinition(RememberMeProcessingFilter.class);
135 filter.setSource(source);
136 filter.getPropertyValues().addPropertyValue("authenticationManager",
137 new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
138
139 filter.getPropertyValues().addPropertyValue("rememberMeServices",
140 new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES));
141
142 pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_FILTER, filter);
143 ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.REMEMBER_ME_FILTER));
144 }
145 }