Browse Source

SEC:1263: Added FactoryBean for AuthenticationManager

Luke Taylor 16 years ago
parent
commit
ac5237c127

+ 50 - 0
config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java

@@ -0,0 +1,50 @@
+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;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.config.BeanIds;
+
+/**
+ * Factory bean for the namespace AuthenticationManager, which allows a more meaningful error message
+ * to be reported in the <tt>NoSuchBeanDefinitionException</tt>, if the user has forgotten to declare
+ * the &lt;authentication-manager&gt; element.
+ *
+ * @author Luke Taylor
+ * @version $Id$
+ * @since 3.0
+ */
+public class AuthenticationManagerFactoryBean implements FactoryBean<AuthenticationManager>, BeanFactoryAware {
+    private final Log logger = LogFactory.getLog(getClass());
+    private BeanFactory bf;
+
+    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 ?");
+        }
+    }
+
+    public Class<? extends AuthenticationManager> getObjectType() {
+        return ProviderManager.class;
+    }
+
+    public boolean isSingleton() {
+        return true;
+    }
+
+    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+        bf = beanFactory;
+    }
+
+}

+ 0 - 59
config/src/main/java/org/springframework/security/config/authentication/NamespaceAuthenticationManager.java

@@ -1,59 +0,0 @@
-package org.springframework.security.config.authentication;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.BeanFactoryAware;
-import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.authentication.ProviderManager;
-import org.springframework.util.Assert;
-
-/**
- * Extended version of {@link ProviderManager the default authentication manager} which lazily initializes
- * the list of {@link AuthenticationProvider}s. This prevents some of the issues that have occurred with
- * namespace configuration where early instantiation of a security interceptor has caused the AuthenticationManager
- * and thus dependent beans (typically UserDetailsService implementations or DAOs) to be initialized too early.
- *
- * @author Luke Taylor
- * @since 2.0.4
- */
-public class NamespaceAuthenticationManager extends ProviderManager implements BeanFactoryAware {
-    private BeanFactory beanFactory;
-    private List<String> providerBeanNames;
-
-    public void setBeanFactory(BeanFactory beanFactory) {
-        this.beanFactory = beanFactory;
-    }
-
-    public void afterPropertiesSet() throws Exception {
-        Assert.notNull(providerBeanNames, "provideBeanNames has not been set");
-        Assert.notEmpty(providerBeanNames, "No authentication providers were found in the application context");
-    }
-
-    /**
-     * Overridden to lazily-initialize the list of providers on first use.
-     */
-    public List<AuthenticationProvider> getProviders() {
-        // We use the names array to determine whether the list has been set yet.
-        if (providerBeanNames != null) {
-            ArrayList<AuthenticationProvider> providers = new ArrayList<AuthenticationProvider>();
-            Iterator<String> beanNames = providerBeanNames.iterator();
-
-            while (beanNames.hasNext()) {
-                providers.add((AuthenticationProvider) beanFactory.getBean(beanNames.next()));
-            }
-            providerBeanNames = null;
-            providers.trimToSize();
-
-            setProviders(providers);
-        }
-
-        return super.getProviders();
-    }
-
-    public void setProviderBeanNames(List<String> provideBeanNames) {
-        this.providerBeanNames = provideBeanNames;
-    }
-}

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

@@ -26,6 +26,7 @@ import org.springframework.core.Ordered;
 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.web.FilterChainProxy;
 import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
 import org.springframework.security.web.util.AntUrlPathMatcher;
@@ -171,7 +172,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
     private BeanReference createAuthenticationManager(Element element, ParserContext pc,
             ManagedList<BeanReference> authenticationProviders, BeanReference concurrencyController) {
         BeanDefinitionBuilder authManager = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class);
-        authManager.addPropertyReference("parent", BeanIds.AUTHENTICATION_MANAGER);
+        authManager.addPropertyValue("parent", new RootBeanDefinition(AuthenticationManagerFactoryBean.class));
         authManager.addPropertyValue("providers", authenticationProviders);
 
         if (concurrencyController != null) {