SEC-1210: RememberMe filter misses UserDetailsService in default <http /> 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.

This commit is contained in:
Luke Taylor 2009-07-31 19:40:20 +00:00
parent 160aa512a1
commit c5d6484b54
2 changed files with 33 additions and 3 deletions

View File

@ -7,6 +7,8 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue; import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; 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.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 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 * 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. * if available so should not be used for beans which need to separate the two.
*/ */
UserDetailsService getUserDetailsService() { UserDetailsService getUserDetailsService() {
Map<String,?> beans = beanFactory.getBeansOfType(CachingUserDetailsService.class); Map<String,?> beans = getBeansOfType(CachingUserDetailsService.class);
if (beans.size() == 0) { if (beans.size() == 0) {
beans = beanFactory.getBeansOfType(UserDetailsService.class); beans = getBeansOfType(UserDetailsService.class);
} }
if (beans.size() == 0) { if (beans.size() == 0) {
@ -146,6 +147,25 @@ public class UserDetailsServiceInjectionBeanPostProcessor implements BeanPostPro
return null; return null;
} }
private Map<String,?> getBeansOfType(Class<?> type) {
Map<String,?> 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 { public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;

View File

@ -938,6 +938,16 @@ public class HttpSecurityBeanDefinitionParserTests {
assertEquals(Boolean.TRUE, FieldUtils.getFieldValue(filter, "repo.disableUrlRewriting")); assertEquals(Boolean.TRUE, FieldUtils.getFieldValue(filter, "repo.disableUrlRewriting"));
} }
@Test
public void userDetailsServiceInParentContextIsLocatedSuccessfully() throws Exception {
appContext = new InMemoryXmlApplicationContext(AUTH_PROVIDER_XML);
appContext = new InMemoryXmlApplicationContext(
"<http auto-config='true'>" +
" <remember-me />" +
"</http>", appContext);
}
private void setContext(String context) { private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context); appContext = new InMemoryXmlApplicationContext(context);
} }