From c5d6484b547e2914edcd71e01549f2c11c4f65ec Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Fri, 31 Jul 2009 19:40:20 +0000 Subject: [PATCH] SEC-1210: RememberMe filter misses UserDetailsService in default tag config when it is declared in parent app context. Fixed by getting the UserDetailsServiceInjectionPostProcessor to check ancestor bean factories for a UserDetailsService if one isn't found in the current bean factory. --- ...ailsServiceInjectionBeanPostProcessor.java | 26 ++++++++++++++++--- ...HttpSecurityBeanDefinitionParserTests.java | 10 +++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceInjectionBeanPostProcessor.java b/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceInjectionBeanPostProcessor.java index 1132155886..4b17f75bdb 100644 --- a/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceInjectionBeanPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceInjectionBeanPostProcessor.java @@ -7,6 +7,8 @@ import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.HierarchicalBeanFactory; +import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; @@ -108,16 +110,15 @@ public class UserDetailsServiceInjectionBeanPostProcessor implements BeanPostPro } } - /** * Obtains a user details service for use in RememberMeServices etc. Will return a caching version * if available so should not be used for beans which need to separate the two. */ UserDetailsService getUserDetailsService() { - Map beans = beanFactory.getBeansOfType(CachingUserDetailsService.class); + Map beans = getBeansOfType(CachingUserDetailsService.class); if (beans.size() == 0) { - beans = beanFactory.getBeansOfType(UserDetailsService.class); + beans = getBeansOfType(UserDetailsService.class); } if (beans.size() == 0) { @@ -146,6 +147,25 @@ public class UserDetailsServiceInjectionBeanPostProcessor implements BeanPostPro return null; } + private Map getBeansOfType(Class type) { + Map beans = beanFactory.getBeansOfType(type); + + // Check ancestor bean factories if they exist and the current one has none of the required type + BeanFactory parent = beanFactory.getParentBeanFactory(); + while (parent != null && beans.size() == 0) { + if (parent instanceof ListableBeanFactory) { + beans = ((ListableBeanFactory)parent).getBeansOfType(type); + } + if (parent instanceof HierarchicalBeanFactory) { + parent = ((HierarchicalBeanFactory)parent).getParentBeanFactory(); + } else { + break; + } + } + + return beans; + } + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; diff --git a/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java index 18a6812e23..8c20f2c75e 100644 --- a/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java @@ -938,6 +938,16 @@ public class HttpSecurityBeanDefinitionParserTests { assertEquals(Boolean.TRUE, FieldUtils.getFieldValue(filter, "repo.disableUrlRewriting")); } + @Test + public void userDetailsServiceInParentContextIsLocatedSuccessfully() throws Exception { + appContext = new InMemoryXmlApplicationContext(AUTH_PROVIDER_XML); + + appContext = new InMemoryXmlApplicationContext( + "" + + " " + + "", appContext); + } + private void setContext(String context) { appContext = new InMemoryXmlApplicationContext(context); }