Explorar o código

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 %!s(int64=16) %!d(string=hai) anos
pai
achega
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 $
  */
 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 */
     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;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.BeanFactory;
 import org.springframework.beans.factory.BeanFactoryAware;
@@ -21,17 +19,18 @@ import org.springframework.security.config.BeanIds;
  * @since 3.0
  */
 public class AuthenticationManagerFactoryBean implements FactoryBean<AuthenticationManager>, BeanFactoryAware {
-    private final Log logger = LogFactory.getLog(getClass());
     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 {
         try {
              return (AuthenticationManager) bf.getBean(BeanIds.AUTHENTICATION_MANAGER);
         } 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.factory.BeanFactory;
 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.BeanReference;
 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.config.BeanIds;
 import org.springframework.security.config.Elements;
+import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 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_ADVICE_ORDER = "order";
 
- //   @SuppressWarnings("unchecked")
     public BeanDefinition parse(Element element, ParserContext pc) {
         CompositeComponentDefinition compositeDef =
             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) {
         BeanDefinitionBuilder bldr = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class);
         bldr.getRawBeanDefinition().setSource(source);
-
         bldr.addPropertyReference("accessDecisionManager", accessManagerId);
         bldr.addPropertyValue("authenticationManager", new RootBeanDefinition(AuthenticationManagerDelegator.class));
         bldr.addPropertyValue("securityMetadataSource", metadataSource);
@@ -335,7 +335,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
      * @author Luke Taylor
      * @since 3.0
      */
-    public static final class AuthenticationManagerDelegator implements AuthenticationManager, BeanFactoryAware {
+    static final class AuthenticationManagerDelegator implements AuthenticationManager, BeanFactoryAware {
         private AuthenticationManager delegate;
         private final Object delegateMonitor = new Object();
         private BeanFactory beanFactory;
@@ -344,7 +344,15 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
             synchronized(delegateMonitor) {
                 if (delegate == null) {
                     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;
 
+import static org.junit.Assert.*;
+
 import org.junit.After;
 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.security.config.authentication.AuthenticationManagerFactoryBean;
 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
- * transform has not been applied. 
- * 
+ * transform has not been applied.
+ *
  * @author Luke Taylor
  * @version $Id$
  */
 public class InvalidConfigurationTests {
     private InMemoryXmlApplicationContext appContext;
-    
+
     @After
     public void closeAppContext() {
         if (appContext != null) {
             appContext.close();
         }
-    }   
-    
+    }
+
     // Parser should throw a SAXParseException
     @Test(expected=XmlBeanDefinitionStoreException.class)
     public void passwordEncoderCannotAppearAtTopLevel() {
         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) {
         appContext = new InMemoryXmlApplicationContext(context);
     }