瀏覽代碼

SEC-1263: Add FactoryBean for namespace AuthenticationManager. <http> now uses AuthenticationManagerFactoryBean. Method security already uses a delegate object to lookup the AuthenticationManager. This now uses the same error message if the bean isn't found, rather than allowing the BeanFactory NoSuchBeanDefinitionException to be thrown directly.

Luke Taylor 16 年之前
父節點
當前提交
ed2ddf9323

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

@@ -9,7 +9,7 @@ package org.springframework.security.config;
  * @version $Id: BeanIds.java 3770 2009-07-15 23:09:47Z ltaylor $
  * @version $Id: BeanIds.java 3770 2009-07-15 23:09:47Z ltaylor $
  */
  */
 public abstract class BeanIds {
 public abstract class BeanIds {
-    private static final String PREFIX = "org.springframework.security";
+    private static final String PREFIX = "org.springframework.security.";
 
 
     /** The "global" AuthenticationManager instance, registered by the <authentication-manager> element */
     /** The "global" AuthenticationManager instance, registered by the <authentication-manager> element */
     public static final String AUTHENTICATION_MANAGER = PREFIX + "authenticationManager";
     public static final String AUTHENTICATION_MANAGER = PREFIX + "authenticationManager";

+ 6 - 7
config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java

@@ -1,7 +1,5 @@
 package org.springframework.security.config.authentication;
 package org.springframework.security.config.authentication;
 
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.BeanFactory;
 import org.springframework.beans.factory.BeanFactory;
 import org.springframework.beans.factory.BeanFactoryAware;
 import org.springframework.beans.factory.BeanFactoryAware;
@@ -21,17 +19,18 @@ import org.springframework.security.config.BeanIds;
  * @since 3.0
  * @since 3.0
  */
  */
 public class AuthenticationManagerFactoryBean implements FactoryBean<AuthenticationManager>, BeanFactoryAware {
 public class AuthenticationManagerFactoryBean implements FactoryBean<AuthenticationManager>, BeanFactoryAware {
-    private final Log logger = LogFactory.getLog(getClass());
     private BeanFactory bf;
     private BeanFactory bf;
+    public static final String MISSING_BEAN_ERROR_MESSAGE = "Did you forget to add an <authentication-manager> element " +
+            "to your configuration (with child <authentication-provider> elements) ?";
 
 
     public AuthenticationManager getObject() throws Exception {
     public AuthenticationManager getObject() throws Exception {
         try {
         try {
              return (AuthenticationManager) bf.getBean(BeanIds.AUTHENTICATION_MANAGER);
              return (AuthenticationManager) bf.getBean(BeanIds.AUTHENTICATION_MANAGER);
         } catch (NoSuchBeanDefinitionException e) {
         } catch (NoSuchBeanDefinitionException e) {
-            logger.error(BeanIds.AUTHENTICATION_MANAGER + " bean was not found in the application context.");
-            throw new NoSuchBeanDefinitionException("The namespace AuthenticationManager was not found. " +
-                    "Did you forget to add an <authentication-manager> element to your configuration with " +
-                    "child <authentication-provider> elements ?");
+            if (BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) {
+                throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, MISSING_BEAN_ERROR_MESSAGE);
+            }
+            throw e;
         }
         }
     }
     }
 
 

+ 12 - 4
config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java

@@ -14,6 +14,7 @@ import org.springframework.beans.BeanMetadataElement;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.BeansException;
 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.NoSuchBeanDefinitionException;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.config.BeanReference;
 import org.springframework.beans.factory.config.BeanReference;
 import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.config.RuntimeBeanReference;
@@ -48,6 +49,7 @@ import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.ProviderManager;
 import org.springframework.security.authentication.ProviderManager;
 import org.springframework.security.config.BeanIds;
 import org.springframework.security.config.BeanIds;
 import org.springframework.security.config.Elements;
 import org.springframework.security.config.Elements;
+import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.util.Assert;
 import org.springframework.util.Assert;
@@ -77,7 +79,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
     private static final String ATT_REF = "ref";
     private static final String ATT_REF = "ref";
     private static final String ATT_ADVICE_ORDER = "order";
     private static final String ATT_ADVICE_ORDER = "order";
 
 
- //   @SuppressWarnings("unchecked")
     public BeanDefinition parse(Element element, ParserContext pc) {
     public BeanDefinition parse(Element element, ParserContext pc) {
         CompositeComponentDefinition compositeDef =
         CompositeComponentDefinition compositeDef =
             new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
             new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
@@ -287,7 +288,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
             String runAsManagerId, BeanReference metadataSource, List<BeanMetadataElement> afterInvocationProviders, Object source) {
             String runAsManagerId, BeanReference metadataSource, List<BeanMetadataElement> afterInvocationProviders, Object source) {
         BeanDefinitionBuilder bldr = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class);
         BeanDefinitionBuilder bldr = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class);
         bldr.getRawBeanDefinition().setSource(source);
         bldr.getRawBeanDefinition().setSource(source);
-
         bldr.addPropertyReference("accessDecisionManager", accessManagerId);
         bldr.addPropertyReference("accessDecisionManager", accessManagerId);
         bldr.addPropertyValue("authenticationManager", new RootBeanDefinition(AuthenticationManagerDelegator.class));
         bldr.addPropertyValue("authenticationManager", new RootBeanDefinition(AuthenticationManagerDelegator.class));
         bldr.addPropertyValue("securityMetadataSource", metadataSource);
         bldr.addPropertyValue("securityMetadataSource", metadataSource);
@@ -335,7 +335,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
      * @author Luke Taylor
      * @author Luke Taylor
      * @since 3.0
      * @since 3.0
      */
      */
-    public static final class AuthenticationManagerDelegator implements AuthenticationManager, BeanFactoryAware {
+    static final class AuthenticationManagerDelegator implements AuthenticationManager, BeanFactoryAware {
         private AuthenticationManager delegate;
         private AuthenticationManager delegate;
         private final Object delegateMonitor = new Object();
         private final Object delegateMonitor = new Object();
         private BeanFactory beanFactory;
         private BeanFactory beanFactory;
@@ -344,7 +344,15 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
             synchronized(delegateMonitor) {
             synchronized(delegateMonitor) {
                 if (delegate == null) {
                 if (delegate == null) {
                     Assert.state(beanFactory != null, "BeanFactory must be set to resolve " + BeanIds.AUTHENTICATION_MANAGER);
                     Assert.state(beanFactory != null, "BeanFactory must be set to resolve " + BeanIds.AUTHENTICATION_MANAGER);
-                    delegate = beanFactory.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
+                    try {
+                        delegate = beanFactory.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
+                    } catch (NoSuchBeanDefinitionException e) {
+                        if (BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) {
+                            throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER,
+                                AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE);
+                        }
+                        throw e;
+                    }
                 }
                 }
             }
             }
 
 

+ 29 - 7
config/src/test/java/org/springframework/security/config/InvalidConfigurationTests.java

@@ -1,34 +1,56 @@
 package org.springframework.security.config;
 package org.springframework.security.config;
 
 
+import static org.junit.Assert.*;
+
 import org.junit.After;
 import org.junit.After;
 import org.junit.Test;
 import org.junit.Test;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 import org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException;
 import org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException;
+import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
 import org.springframework.security.config.util.InMemoryXmlApplicationContext;
 import org.springframework.security.config.util.InMemoryXmlApplicationContext;
 
 
 /**
 /**
- * Tests which make sure invalid configurations are rejected by the namespace. In particular invalid top-level 
+ * Tests which make sure invalid configurations are rejected by the namespace. In particular invalid top-level
  * elements. These are likely to fail after the namespace has been updated using trang, but the spring-security.xsl
  * elements. These are likely to fail after the namespace has been updated using trang, but the spring-security.xsl
- * transform has not been applied. 
- * 
+ * transform has not been applied.
+ *
  * @author Luke Taylor
  * @author Luke Taylor
  * @version $Id$
  * @version $Id$
  */
  */
 public class InvalidConfigurationTests {
 public class InvalidConfigurationTests {
     private InMemoryXmlApplicationContext appContext;
     private InMemoryXmlApplicationContext appContext;
-    
+
     @After
     @After
     public void closeAppContext() {
     public void closeAppContext() {
         if (appContext != null) {
         if (appContext != null) {
             appContext.close();
             appContext.close();
         }
         }
-    }   
-    
+    }
+
     // Parser should throw a SAXParseException
     // Parser should throw a SAXParseException
     @Test(expected=XmlBeanDefinitionStoreException.class)
     @Test(expected=XmlBeanDefinitionStoreException.class)
     public void passwordEncoderCannotAppearAtTopLevel() {
     public void passwordEncoderCannotAppearAtTopLevel() {
         setContext("<password-encoder hash='md5'/>");
         setContext("<password-encoder hash='md5'/>");
     }
     }
-    
+
+    @Test(expected=XmlBeanDefinitionStoreException.class)
+    public void authenticationProviderCannotAppearAtTopLevel() {
+        setContext("<authentication-provider ref='blah'/>");
+    }
+
+    @Test
+    public void missingAuthenticationManagerGivesSensibleErrorMessage() {
+        try {
+            setContext("<http auto-config='true' />");
+        } catch (BeanCreationException e) {
+            assertTrue(e.getCause().getCause() instanceof NoSuchBeanDefinitionException);
+            NoSuchBeanDefinitionException nsbe = (NoSuchBeanDefinitionException) e.getCause().getCause();
+            assertEquals(BeanIds.AUTHENTICATION_MANAGER, nsbe.getBeanName());
+            assertTrue(nsbe.getMessage().endsWith(AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE));
+        }
+    }
+
     private void setContext(String context) {
     private void setContext(String context) {
         appContext = new InMemoryXmlApplicationContext(context);
         appContext = new InMemoryXmlApplicationContext(context);
     }
     }