SEC-909: custom remember me services doesn't get registered as logout handler

http://jira.springframework.org/browse/SEC-909. HttpSecurityBeanDefinitionParser now passes the resolved RememberMeServices bean name to the LogoutBeanDefinitionparser so that it an use it explicitly.
This commit is contained in:
Luke Taylor 2008-07-15 18:22:53 +00:00
parent 1ddc033fe5
commit f453264bde
5 changed files with 47 additions and 20 deletions

View File

@ -159,20 +159,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
new AnonymousBeanDefinitionParser().parse(anonymousElt, parserContext);
}
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
Element rememberMeElt = DomUtils.getChildElementByTagName(element, Elements.REMEMBER_ME);
if (rememberMeElt != null || autoConfig) {
new RememberMeBeanDefinitionParser().parse(rememberMeElt, parserContext);
// Post processor to inject RememberMeServices into filters which need it
RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor);
}
Element logoutElt = DomUtils.getChildElementByTagName(element, Elements.LOGOUT);
if (logoutElt != null || autoConfig) {
new LogoutBeanDefinitionParser().parse(logoutElt, parserContext);
}
parseRememberMeAndLogout(element, autoConfig, parserContext);
parseBasicFormLoginAndOpenID(element, parserContext, autoConfig, allowSessionCreation);
@ -192,6 +179,27 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
return null;
}
private void parseRememberMeAndLogout(Element elt, boolean autoConfig, ParserContext pc) {
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
Element rememberMeElt = DomUtils.getChildElementByTagName(elt, Elements.REMEMBER_ME);
String rememberMeServices = null;
if (rememberMeElt != null || autoConfig) {
RememberMeBeanDefinitionParser rmbdp = new RememberMeBeanDefinitionParser();
rmbdp.parse(rememberMeElt, pc);
rememberMeServices = rmbdp.getServicesName();
// Post processor to inject RememberMeServices into filters which need it
RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor);
}
Element logoutElt = DomUtils.getChildElementByTagName(elt, Elements.LOGOUT);
if (logoutElt != null || autoConfig) {
new LogoutBeanDefinitionParser(rememberMeServices).parse(logoutElt, pc);
}
}
private void registerFilterChainProxy(ParserContext pc, Map filterChainMap, UrlMatcher matcher, Object source) {
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
pc.getReaderContext().error("Duplicate <http> element detected", source);

View File

@ -25,6 +25,12 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser {
static final String ATT_LOGOUT_URL = "logout-url";
static final String DEF_LOGOUT_URL = "/j_spring_security_logout";
String rememberMeServices;
public LogoutBeanDefinitionParser(String rememberMeServices) {
this.rememberMeServices = rememberMeServices;
}
public BeanDefinition parse(Element element, ParserContext parserContext) {
String logoutUrl = null;
@ -66,8 +72,8 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser {
}
handlers.add(sclh);
if (parserContext.getRegistry().containsBeanDefinition(BeanIds.REMEMBER_ME_SERVICES)) {
handlers.add(new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES));
if (rememberMeServices != null) {
handlers.add(new RuntimeBeanReference(rememberMeServices));
}
builder.addConstructorArg(handlers);

View File

@ -32,6 +32,7 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
static final String ATT_TOKEN_VALIDITY = "token-validity-seconds";
protected final Log logger = LogFactory.getLog(getClass());
private String servicesName;
public BeanDefinition parse(Element element, ParserContext parserContext) {
String tokenRepository = null;
@ -102,8 +103,10 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
}
services.setSource(source);
services.getPropertyValues().addPropertyValue(ATT_KEY, key);
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services);
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services);
servicesName = BeanIds.REMEMBER_ME_SERVICES;
} else {
servicesName = rememberMeServicesRef;
parserContext.getRegistry().registerAlias(rememberMeServicesRef, BeanIds.REMEMBER_ME_SERVICES);
}
@ -114,7 +117,11 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
return null;
}
private void registerProvider(ParserContext pc, Object source, String key) {
String getServicesName() {
return servicesName;
}
private void registerProvider(ParserContext pc, Object source, String key) {
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(pc);
RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class);
provider.setSource(source);

View File

@ -51,7 +51,8 @@ public class RememberMeServicesInjectionBeanPostProcessor implements BeanPostPro
Map beans = beanFactory.getBeansOfType(RememberMeServices.class);
Assert.isTrue(beans.size() > 0, "No RememberMeServices configured");
Assert.isTrue(beans.size() == 1, "More than one RememberMeServices bean found.");
Assert.isTrue(beans.size() == 1, "Use of '<remember-me />' requires a single instance of RememberMeServices " +
"in the application context, but more than one was found.");
return (RememberMeServices) beans.values().toArray()[0];
}

View File

@ -34,6 +34,7 @@ import org.springframework.security.ui.SessionFixationProtectionFilter;
import org.springframework.security.ui.WebAuthenticationDetails;
import org.springframework.security.ui.basicauth.BasicProcessingFilter;
import org.springframework.security.ui.logout.LogoutFilter;
import org.springframework.security.ui.logout.LogoutHandler;
import org.springframework.security.ui.preauth.x509.X509PreAuthenticatedProcessingFilter;
import org.springframework.security.ui.rememberme.NullRememberMeServices;
import org.springframework.security.ui.rememberme.PersistentTokenBasedRememberMeServices;
@ -378,7 +379,11 @@ public class HttpSecurityBeanDefinitionParserTests {
AUTH_PROVIDER_XML);
assertEquals(5000, FieldUtils.getFieldValue(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES),
"tokenValiditySeconds"));
"tokenValiditySeconds"));
// SEC-909
LogoutHandler[] logoutHandlers = (LogoutHandler[]) FieldUtils.getFieldValue(appContext.getBean(BeanIds.LOGOUT_FILTER), "handlers");
assertEquals(2, logoutHandlers.length);
assertEquals(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES), logoutHandlers[1]);
}
@Test