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

Remove use of autoconfig, as it was really just a conveniece for creating default access and authentication managers.

Luke Taylor 18 жил өмнө
parent
commit
1bcb62af2e

+ 78 - 0
core/src/main/java/org/springframework/security/config/ConfigUtils.java

@@ -0,0 +1,78 @@
+package org.springframework.security.config;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.security.AccessDecisionManager;
+import org.springframework.security.AuthenticationManager;
+import org.springframework.security.vote.AffirmativeBased;
+import org.springframework.security.vote.AuthenticatedVoter;
+import org.springframework.security.vote.RoleVoter;
+import org.springframework.util.Assert;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * @author Luke Taylor
+ * @version $Id$
+ */
+public abstract class ConfigUtils {
+    public static final String DEFAULT_ACCESS_MANAGER_ID = "_accessManager";
+
+    static void registerAccessManagerIfNecessary(ConfigurableListableBeanFactory bf) {
+        if (bf.getBeanNamesForType(AccessDecisionManager.class).length > 0) {
+            return;
+        }
+
+        Assert.isInstanceOf(BeanDefinitionRegistry.class, bf, " Auto-registration of default AccessManager will only work " +
+                "with a BeanFactory which implements BeanDefinitionRegistry");
+
+        BeanDefinitionRegistry registry = (BeanDefinitionRegistry)bf;
+
+        if (!registry.containsBeanDefinition(DEFAULT_ACCESS_MANAGER_ID)) {
+            BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class);
+            accessMgrBuilder.addPropertyValue("decisionVoters",
+                            Arrays.asList(new Object[] {new RoleVoter(), new AuthenticatedVoter()}));    
+            BeanDefinition accessMgr = accessMgrBuilder.getBeanDefinition();
+
+            registry.registerBeanDefinition(DEFAULT_ACCESS_MANAGER_ID, accessMgr);
+        }
+    }
+
+    static AuthenticationManager getAuthenticationManager(ConfigurableListableBeanFactory bf) {
+        Map authManagers = bf.getBeansOfType(AuthenticationManager.class);
+
+        if (authManagers.size() == 0) {
+            throw new IllegalArgumentException("No AuthenticationManager registered. " +
+                    "Make sure you have configured at least one AuthenticationProvider?");
+
+        } else if (authManagers.size() > 1) {
+            throw new IllegalArgumentException("More than one AuthenticationManager registered.");
+        }
+
+        AuthenticationManager accessMgr = (AuthenticationManager) authManagers.values().toArray()[0];
+
+        return accessMgr;
+    }
+
+    static void configureSecurityInterceptor(ConfigurableListableBeanFactory beanFactory,
+            BeanDefinition securityInterceptor) {
+        
+        ConfigUtils.registerAccessManagerIfNecessary(beanFactory);
+
+        Map accessManagers = beanFactory.getBeansOfType(AccessDecisionManager.class);
+
+        if (accessManagers.size() > 1) {
+            throw new IllegalArgumentException("More than one AccessDecisionManager registered. Please specify one " +
+                    "  using the TODO attribute.");
+        }
+
+        AccessDecisionManager accessMgr = (AccessDecisionManager) accessManagers.values().toArray()[0];
+
+        securityInterceptor.getPropertyValues().addPropertyValue("accessDecisionManager", accessMgr);
+        securityInterceptor.getPropertyValues().addPropertyValue("authenticationManager",
+                getAuthenticationManager(beanFactory));
+    }
+}

+ 1 - 1
core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java

@@ -88,7 +88,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         filterSecurityInterceptorBuilder.addPropertyValue("objectDefinitionSource", interceptorFilterInvDefSource);
 
         // Again pick up auth manager
-        filterSecurityInterceptorBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
+        //filterSecurityInterceptorBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
 
         parseInterceptUrls(DomUtils.getChildElementsByTagName(element, "intercept-url"),
                 filterChainMap, interceptorFilterInvDefSource);

+ 20 - 4
core/src/main/java/org/springframework/security/config/HttpSecurityConfigPostProcessor.java

@@ -8,6 +8,7 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 import org.springframework.core.OrderComparator;
 import org.springframework.core.Ordered;
+import org.springframework.security.AccessDecisionManager;
 import org.springframework.security.AuthenticationManager;
 import org.springframework.security.context.HttpSessionContextIntegrationFilter;
 import org.springframework.security.ui.AuthenticationEntryPoint;
@@ -15,7 +16,11 @@ import org.springframework.security.util.FilterChainProxy;
 import org.springframework.util.Assert;
 
 import javax.servlet.Filter;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Responsible for tying up the HTTP security configuration - building ordered filter stack and linking up
@@ -26,18 +31,29 @@ import java.util.*;
  */
 public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered {
     private Log logger = LogFactory.getLog(getClass());
+    private AuthenticationManager authManager;
 
     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
         HttpSessionContextIntegrationFilter httpSCIF = (HttpSessionContextIntegrationFilter)
                 beanFactory.getBean(HttpSecurityBeanDefinitionParser.DEFAULT_HTTP_SESSION_FILTER_ID);
-        AuthenticationManager authManager =
-                (AuthenticationManager) getBeanOfType(AuthenticationManager.class, beanFactory);
+        authManager = ConfigUtils.getAuthenticationManager(beanFactory);
 
         configureAuthenticationEntryPoint(beanFactory);
 
+        configureFilterSecurityInterceptor(beanFactory);
+
         configureFilterChain(beanFactory);
     }
 
+    private void configureFilterSecurityInterceptor(ConfigurableListableBeanFactory beanFactory) {
+        ConfigUtils.registerAccessManagerIfNecessary(beanFactory);
+
+        BeanDefinition securityInterceptor =
+                beanFactory.getBeanDefinition(HttpSecurityBeanDefinitionParser.DEFAULT_FILTER_SECURITY_INTERCEPTOR_ID);
+
+        ConfigUtils.configureSecurityInterceptor(beanFactory, securityInterceptor);
+    }
+
     /**
      * Selects the entry point that should be used in ExceptionTranslationFilter. Strategy is
      *
@@ -127,6 +143,6 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
     }
 
     public int getOrder() {
-        return 0;
+        return HIGHEST_PRECEDENCE;
     }
 }

+ 60 - 8
core/src/main/java/org/springframework/security/config/InterceptMethodsBeanDefinitionDecorator.java

@@ -1,24 +1,78 @@
 package org.springframework.security.config;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator;
+import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanDefinitionHolder;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor;
-import org.springframework.security.intercept.method.MethodDefinitionMap;
-import org.springframework.security.ConfigAttributeEditor;
+import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.core.Ordered;
 import org.springframework.security.ConfigAttributeDefinition;
+import org.springframework.security.ConfigAttributeEditor;
+import org.springframework.security.intercept.method.MethodDefinitionMap;
+import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor;
 import org.springframework.util.xml.DomUtils;
-import org.w3c.dom.Node;
 import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 
-import java.util.List;
 import java.util.Iterator;
+import java.util.List;
 
 /**
  * @author Luke Taylor
  * @version $Id$
  */
-public class InterceptMethodsBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator {
+public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDecorator {
+    private static final String POST_PROCESSOR_ID = "_interceptMethodsBeanfactoryPP";
+
+    private BeanDefinitionDecorator delegate = new InternalInterceptMethodsBeanDefinitionDecorator();
+
+    public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
+        registerPostProcessorIfNecessary(parserContext.getRegistry());
+
+        return delegate.decorate(node, definition, parserContext);
+    }
+
+    private void registerPostProcessorIfNecessary(BeanDefinitionRegistry registry) {
+        if (registry.containsBeanDefinition(POST_PROCESSOR_ID)) {
+            return;
+        }
+
+        registry.registerBeanDefinition(POST_PROCESSOR_ID,
+                new RootBeanDefinition(MethodSecurityConfigPostProcessor.class));
+    }
+
+    public static class MethodSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered {
+
+        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+            String[] interceptors = beanFactory.getBeanNamesForType(MethodSecurityInterceptor.class);
+
+            for (int i=0; i < interceptors.length; i++) {
+                BeanDefinition interceptor = beanFactory.getBeanDefinition(interceptors[i]);
+                ConfigUtils.configureSecurityInterceptor(beanFactory, interceptor);
+            }
+        }
+
+        public int getOrder() {
+            return HIGHEST_PRECEDENCE;
+        }
+
+    }
+}
+
+/**
+ * This is the real class which does the work. We need acccess to the ParserContext in order to register the
+ * post processor,
+ */
+class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator {
+    private Log logger = LogFactory.getLog(getClass());
+
     protected BeanDefinition createInterceptorDefinition(Node node) {
         Element interceptMethodsElt = (Element)node;
         RootBeanDefinition interceptor = new RootBeanDefinition(MethodSecurityInterceptor.class);
@@ -53,8 +107,6 @@ public class InterceptMethodsBeanDefinitionDecorator extends AbstractInterceptor
 
         interceptor.getPropertyValues().addPropertyValue("objectDefinitionSource", methodMap);
 
-        interceptor.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
-
         return interceptor;
     }
 }

+ 0 - 1
core/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java

@@ -15,7 +15,6 @@ public class SecurityNamespaceHandler extends NamespaceHandlerSupport {
         registerBeanDefinitionParser("http", new HttpSecurityBeanDefinitionParser());
         registerBeanDefinitionParser("user-service", new UserServiceBeanDefinitionParser());
         registerBeanDefinitionParser("authentication-provider", new AuthenticationProviderBeanDefinitionParser());
-        registerBeanDefinitionParser("autoconfig", new AutoConfigBeanDefinitionParser());
         registerBeanDefinitionDecorator("intercept-methods", new InterceptMethodsBeanDefinitionDecorator());
         registerBeanDefinitionDecorator("filter-chain-map", new FilterChainMapBeanDefinitionDecorator());        
     }

+ 0 - 4
core/src/test/resources/org/springframework/security/config/http-security.xml

@@ -6,8 +6,6 @@
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
 http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
 
-    <security:autoconfig />
-
     <security:http createSession="ifRequired" pathType="ant" lowerCaseComparisons="true">
         <security:intercept-url pattern="/unprotected" filters="none"/>
         <security:intercept-url pattern="/somepath" access="ROLE_SPECIAL,ROLE_USER" />
@@ -23,12 +21,10 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
         <security:http-basic realm="NamespaceTestRealm"  />
     </security:http>
 
-
     <security:authentication-provider>
         <security:user-service>
             <security:user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" />
             <security:user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
         </security:user-service>
     </security:authentication-provider>
-
 </beans>

+ 0 - 2
core/src/test/resources/org/springframework/security/config/method-security.xml

@@ -6,8 +6,6 @@
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
 http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
 
-    <security:autoconfig />
-
     <bean id="target" class="org.springframework.security.config.TestBusinessBeanImpl">
         <!-- This will add a security interceptor to the bean -->
         <security:intercept-methods>