diff --git a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java new file mode 100644 index 0000000000..1ce25f37ef --- /dev/null +++ b/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 NoSuchBeanDefinitionException, if the user has forgotten to declare + * the <authentication-manager> element. + * + * @author Luke Taylor + * @version $Id$ + * @since 3.0 + */ +public class AuthenticationManagerFactoryBean implements FactoryBean, 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 element to your configuration with " + + "child elements ?"); + } + } + + public Class getObjectType() { + return ProviderManager.class; + } + + public boolean isSingleton() { + return true; + } + + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + bf = beanFactory; + } + +} diff --git a/config/src/main/java/org/springframework/security/config/authentication/NamespaceAuthenticationManager.java b/config/src/main/java/org/springframework/security/config/authentication/NamespaceAuthenticationManager.java deleted file mode 100644 index 4428262bbc..0000000000 --- a/config/src/main/java/org/springframework/security/config/authentication/NamespaceAuthenticationManager.java +++ /dev/null @@ -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 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 getProviders() { - // We use the names array to determine whether the list has been set yet. - if (providerBeanNames != null) { - ArrayList providers = new ArrayList(); - Iterator 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 provideBeanNames) { - this.providerBeanNames = provideBeanNames; - } -} diff --git a/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java index 570f9e28d5..f6d7f7aa91 100644 --- a/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java +++ b/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 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) {