2
0
Эх сурвалжийг харах

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.

Luke Taylor 16 жил өмнө
parent
commit
c5d6484b54

+ 23 - 3
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<String,?> beans = beanFactory.getBeansOfType(CachingUserDetailsService.class);
+        Map<String,?> 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<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 {
         this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;

+ 10 - 0
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(
+                "<http auto-config='true'>" +
+                "    <remember-me />" +
+                "</http>", appContext);
+    }
+
     private void setContext(String context) {
         appContext = new InMemoryXmlApplicationContext(context);
     }