浏览代码

SEC-1195: Added internal AuthenticationManager for use by beans which are generated by the <http> block.

Luke Taylor 16 年之前
父节点
当前提交
1afa67c954

+ 0 - 71
config/src/main/java/org/springframework/security/config/AnonymousBeanDefinitionParser.java

@@ -1,71 +0,0 @@
-package org.springframework.security.config;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.beans.factory.xml.BeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.security.authentication.AnonymousAuthenticationProvider;
-import org.springframework.security.web.authentication.AnonymousProcessingFilter;
-import org.springframework.util.StringUtils;
-import org.w3c.dom.Element;
-
-/**
- * @author Ben Alex
- * @version $Id: RememberMeBeanDefinitionParser.java 2231 2007-11-07 13:29:15Z luke_t $
- */
-public class AnonymousBeanDefinitionParser implements BeanDefinitionParser {
-    static final String ATT_KEY = "key";
-    static final String DEF_KEY = "doesNotMatter";
-
-    static final String ATT_USERNAME = "username";
-    static final String DEF_USERNAME = "anonymousUser";
-
-    static final String ATT_GRANTED_AUTHORITY = "granted-authority";
-    static final String DEF_GRANTED_AUTHORITY = "ROLE_ANONYMOUS";
-
-    protected final Log logger = LogFactory.getLog(getClass());
-
-    public BeanDefinition parse(Element element, ParserContext parserContext) {
-        String grantedAuthority = null;
-        String username = null;
-        String key = null;
-        Object source = null;
-
-        if (element != null) {
-            grantedAuthority = element.getAttribute(ATT_GRANTED_AUTHORITY);
-            username = element.getAttribute(ATT_USERNAME);
-            key = element.getAttribute(ATT_KEY);
-            source = parserContext.extractSource(element);
-        }
-
-        if (!StringUtils.hasText(grantedAuthority)) {
-            grantedAuthority = DEF_GRANTED_AUTHORITY;
-        }
-
-        if (!StringUtils.hasText(username)) {
-            username = DEF_USERNAME;
-        }
-
-        if (!StringUtils.hasText(key)) {
-            key = DEF_KEY;
-        }
-
-        RootBeanDefinition filter = new RootBeanDefinition(AnonymousProcessingFilter.class);
-
-        filter.setSource(source);
-        filter.getPropertyValues().addPropertyValue("userAttribute", username + "," + grantedAuthority);
-        filter.getPropertyValues().addPropertyValue(ATT_KEY, key);
-
-        RootBeanDefinition provider = new RootBeanDefinition(AnonymousAuthenticationProvider.class);
-        provider.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-        provider.setSource(source);
-        provider.getPropertyValues().addPropertyValue(ATT_KEY, key);
-
-        parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER, provider);
-        ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER, null);
-
-        return filter;
-    }
-}

+ 2 - 5
config/src/main/java/org/springframework/security/config/AuthenticationManagerBeanDefinitionParser.java

@@ -1,12 +1,11 @@
 package org.springframework.security.config;
 
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.beans.factory.xml.BeanDefinitionParser;
 import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.util.StringUtils;
-
 import org.w3c.dom.Element;
 
 /**
@@ -34,8 +33,6 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
 
         if (StringUtils.hasText(sessionControllerRef)) {
             BeanDefinition authManager = parserContext.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
-            ConfigUtils.setSessionControllerOnAuthenticationManager(parserContext,
-                    BeanIds.CONCURRENT_SESSION_CONTROLLER, element);
             authManager.getPropertyValues().addPropertyValue("sessionController",
                     new RuntimeBeanReference(sessionControllerRef));
             RootBeanDefinition sessionRegistryInjector = new RootBeanDefinition(SessionRegistryInjectionBeanPostProcessor.class);

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

@@ -13,24 +13,10 @@ public abstract class BeanIds {
     /** External alias for FilterChainProxy bean, for use in web.xml files */
     public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain";
 
-    /** Package protected as end users shouldn't really be using this BFPP directly */
-    static final String INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR = "_interceptMethodsBeanfactoryPP";
     static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor";
-//    static final String ENTRY_POINT_INJECTION_POST_PROCESSOR = "_entryPointInjectionBeanPostProcessor";
-//    static final String USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR = "_userServiceInjectionPostProcessor";
-//    static final String SESSION_REGISTRY_INJECTION_POST_PROCESSOR = "_sessionRegistryInjectionPostProcessor";
-//    static final String FILTER_CHAIN_POST_PROCESSOR = "_filterChainProxyPostProcessor";
-//    static final String FILTER_LIST = "_filterChainList";
 
-//    public static final String JDBC_USER_DETAILS_MANAGER = "_jdbcUserDetailsManager";
     public static final String USER_DETAILS_SERVICE = "_userDetailsService";
-//    public static final String ANONYMOUS_PROCESSING_FILTER = "_anonymousProcessingFilter";
-    public static final String ANONYMOUS_AUTHENTICATION_PROVIDER = "_anonymousAuthenticationProvider";
-//    public static final String BASIC_AUTHENTICATION_FILTER = "_basicAuthenticationFilter";
-    public static final String BASIC_AUTHENTICATION_ENTRY_POINT = "_basicAuthenticationEntryPoint";
-//    public static final String SESSION_REGISTRY = "_sessionRegistry";
-//    public static final String CONCURRENT_SESSION_FILTER = "_concurrentSessionFilter";
-    public static final String CONCURRENT_SESSION_CONTROLLER = "_concurrentSessionController";
+
     public static final String METHOD_ACCESS_MANAGER = "_defaultMethodAccessManager";
     public static final String WEB_ACCESS_MANAGER = "_webAccessManager";
     public static final String AUTHENTICATION_MANAGER = "_authenticationManager";
@@ -39,31 +25,12 @@ public abstract class BeanIds {
     public static final String FORM_LOGIN_ENTRY_POINT = "_formLoginEntryPoint";
     public static final String OPEN_ID_FILTER = "_openIDFilter";
     public static final String OPEN_ID_ENTRY_POINT = "_openIDFilterEntryPoint";
-    public static final String OPEN_ID_PROVIDER = "_openIDAuthenticationProvider";
-//    public static final String MAIN_ENTRY_POINT = "_mainEntryPoint";
+
     public static final String FILTER_CHAIN_PROXY = "_filterChainProxy";
-//    public static final String SECURITY_CONTEXT_PERSISTENCE_FILTER = "_securityContextPersistenceFilter";
     public static final String LDAP_AUTHENTICATION_PROVIDER = "_ldapAuthenticationProvider";
-//    public static final String LOGOUT_FILTER = "_logoutFilter";
-//    public static final String EXCEPTION_TRANSLATION_FILTER = "_exceptionTranslationFilter";
-//    public static final String FILTER_SECURITY_INTERCEPTOR = "_filterSecurityInterceptor";
-//    public static final String CHANNEL_PROCESSING_FILTER = "_channelProcessingFilter";
-    public static final String CHANNEL_DECISION_MANAGER = "_channelDecisionManager";
-//    public static final String REMEMBER_ME_FILTER = "_rememberMeFilter";
-//    public static final String REMEMBER_ME_SERVICES = "_rememberMeServices";
-    public static final String REMEMBER_ME_AUTHENTICATION_PROVIDER = "_rememberMeAuthenticationProvider";
-//    public static final String DEFAULT_LOGIN_PAGE_GENERATING_FILTER = "_defaultLoginPageFilter";
-//    public static final String SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER = "_securityContextHolderAwareRequestFilter";
+
     public static final String SESSION_FIXATION_PROTECTION_FILTER = "_sessionFixationProtectionFilter";
     public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = "_methodSecurityMetadataSourceAdvisor";
-//    public static final String PROTECT_POINTCUT_POST_PROCESSOR = "_protectPointcutPostProcessor";
-//    public static final String SECURED_METHOD_SECURITY_METADATA_SOURCE = "_securedSecurityMetadataSource";
-//    public static final String JSR_250_METHOD_SECURITY_METADATA_SOURCE = "_jsr250SecurityMetadataSource";
     public static final String EMBEDDED_APACHE_DS = "_apacheDirectoryServerContainer";
     public static final String CONTEXT_SOURCE = "_securityContextSource";
-//    public static final String PORT_MAPPER = "_portMapper";
-//    public static final String X509_FILTER = "_x509ProcessingFilter";
-    public static final String X509_AUTH_PROVIDER = "_x509AuthenticationProvider";
-//    public static final String PRE_AUTH_ENTRY_POINT = "_preAuthenticatedProcessingFilterEntryPoint";
-//    public static final String REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR = "_rememberMeServicesInjectionBeanPostProcessor";
 }

+ 0 - 26
config/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java

@@ -26,8 +26,6 @@ import org.w3c.dom.Element;
 public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionParser {
 
     static final String ATT_EXPIRY_URL = "expired-url";
-    static final String ATT_MAX_SESSIONS = "max-sessions";
-    static final String ATT_EXCEPTION_IF_MAX_EXCEEDED = "exception-if-maximum-exceeded";
     static final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias";
     static final String ATT_SESSION_REGISTRY_REF = "session-registry-ref";
 
@@ -67,30 +65,6 @@ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionPar
             filterBuilder.addPropertyValue("expiredUrl", expiryUrl);
         }
 
-        BeanDefinitionBuilder controllerBuilder
-            = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionControllerImpl.class);
-        controllerBuilder.getRawBeanDefinition().setSource(source);
-        controllerBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-        controllerBuilder.addPropertyReference("sessionRegistry", sessionRegistryId);
-
-        String maxSessions = element.getAttribute(ATT_MAX_SESSIONS);
-
-        if (StringUtils.hasText(maxSessions)) {
-            controllerBuilder.addPropertyValue("maximumSessions", maxSessions);
-        }
-
-        String exceptionIfMaximumExceeded = element.getAttribute(ATT_EXCEPTION_IF_MAX_EXCEEDED);
-
-        if (StringUtils.hasText(exceptionIfMaximumExceeded)) {
-            controllerBuilder.addPropertyValue("exceptionIfMaximumExceeded", exceptionIfMaximumExceeded);
-        }
-
-        BeanDefinition controller = controllerBuilder.getBeanDefinition();
-
-        beanRegistry.registerBeanDefinition(BeanIds.CONCURRENT_SESSION_CONTROLLER, controller);
-        pc.registerComponent(new BeanComponentDefinition(controller, BeanIds.CONCURRENT_SESSION_CONTROLLER));
-        ConfigUtils.setSessionControllerOnAuthenticationManager(pc, BeanIds.CONCURRENT_SESSION_CONTROLLER, element);
-
         pc.popAndRegisterContainingComponent();
 
         return filterBuilder.getBeanDefinition();

+ 12 - 16
config/src/main/java/org/springframework/security/config/ConfigUtils.java

@@ -2,9 +2,7 @@ package org.springframework.security.config;
 
 import java.util.ArrayList;
 
-import org.springframework.beans.PropertyValue;
 import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.parsing.BeanComponentDefinition;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 import org.springframework.beans.factory.support.ManagedList;
@@ -27,7 +25,6 @@ import org.w3c.dom.Element;
  * @version $Id$
  */
 abstract class ConfigUtils {
-
     @SuppressWarnings("unchecked")
     static void registerDefaultMethodAccessManagerIfNecessary(ParserContext parserContext) {
         if (!parserContext.getRegistry().containsBeanDefinition(BeanIds.METHOD_ACCESS_MANAGER)) {
@@ -69,7 +66,6 @@ abstract class ConfigUtils {
      * @param element the source element under which this bean should be registered.
      */
     static void registerProviderManagerIfNecessary(ParserContext pc, Element element) {
-
         if(pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER)) {
             return;
         }
@@ -118,16 +114,16 @@ abstract class ConfigUtils {
         pc.getReaderContext().warning(url + " is not a valid redirect URL (must start with '/' or http(s))", source);
     }
 
-    static void setSessionControllerOnAuthenticationManager(ParserContext pc, String beanName, Element sourceElt) {
-        BeanDefinition authManager = pc.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
-        PropertyValue pv = authManager.getPropertyValues().getPropertyValue("sessionController");
-
-        if (pv != null && pv.getValue() != null) {
-            pc.getReaderContext().error("A session controller has already been set on the authentication manager. " +
-                    "The <concurrent-session-control> element isn't compatible with a custom session controller",
-                    pc.extractSource(sourceElt));
-        }
-
-        authManager.getPropertyValues().addPropertyValue("sessionController", new RuntimeBeanReference(beanName));
-    }
+//    static void setSessionControllerOnAuthenticationManager(ParserContext pc, String beanName, Element sourceElt) {
+//        BeanDefinition authManager = pc.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
+//        PropertyValue pv = authManager.getPropertyValues().getPropertyValue("sessionController");
+//
+//        if (pv != null && pv.getValue() != null) {
+//            pc.getReaderContext().error("A session controller has already been set on the authentication manager. " +
+//                    "The <concurrent-session-control> element isn't compatible with a custom session controller",
+//                    pc.extractSource(sourceElt));
+//        }
+//
+//        authManager.getPropertyValues().addPropertyValue("sessionController", new RuntimeBeanReference(beanName));
+//    }
 }

+ 0 - 2
config/src/main/java/org/springframework/security/config/FormLoginBeanDefinitionParser.java

@@ -81,8 +81,6 @@ public class FormLoginBeanDefinitionParser {
         filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, loginPage, authenticationFailureUrl,
                 successHandlerRef, failureHandlerRef);
         filterBean.setSource(source);
-        filterBean.getPropertyValues().addPropertyValue("authenticationManager",
-                new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
 
         // Copy session migration values from the session fixation protection filter
         if (sfpf != null) {

+ 184 - 45
config/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java

@@ -33,6 +33,10 @@ import org.springframework.security.access.SecurityConfig;
 import org.springframework.security.access.vote.AuthenticatedVoter;
 import org.springframework.security.access.vote.RoleVoter;
 import org.springframework.security.authentication.AnonymousAuthenticationProvider;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.authentication.RememberMeAuthenticationProvider;
+import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl;
+import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
 import org.springframework.security.web.FilterChainProxy;
 import org.springframework.security.web.access.AccessDeniedHandlerImpl;
 import org.springframework.security.web.access.ExceptionTranslationFilter;
@@ -48,6 +52,9 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
 import org.springframework.security.web.access.intercept.RequestKey;
 import org.springframework.security.web.authentication.AnonymousProcessingFilter;
 import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
+import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
+import org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor;
+import org.springframework.security.web.authentication.preauth.x509.X509PreAuthenticatedProcessingFilter;
 import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 import org.springframework.security.web.authentication.www.BasicProcessingFilter;
 import org.springframework.security.web.authentication.www.BasicProcessingFilterEntryPoint;
@@ -149,7 +156,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
      * the map of filter chains defined, with the "universal" match pattern mapped to the list of beans which have been parsed here.
      */
     public BeanDefinition parse(Element element, ParserContext pc) {
-        ConfigUtils.registerProviderManagerIfNecessary(pc, element);
+//        ConfigUtils.registerProviderManagerIfNecessary(pc, element);
         CompositeComponentDefinition compositeDef =
             new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
         pc.pushContainingComponent(compositeDef);
@@ -170,6 +177,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
         BeanDefinition cpf = null;
         BeanReference sessionRegistryRef = null;
+        BeanReference concurrentSessionControllerRef = null;
         BeanDefinition concurrentSessionFilter = createConcurrentSessionFilterAndRelatedBeansIfRequired(element, pc);
 
         BeanDefinition scpf = createSecurityContextPersistenceFilter(element, pc);
@@ -179,19 +187,23 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
                     concurrentSessionFilter.getPropertyValues().getPropertyValue("sessionRegistry").getValue();
             logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true");
             scpf.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
+            concurrentSessionControllerRef = createConcurrentSessionController(element, concurrentSessionFilter, sessionRegistryRef, pc);
         }
 
+        ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();
+        BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders, concurrentSessionControllerRef);
+
         BeanDefinition servApiFilter = createServletApiFilter(element, pc);
         // Register the portMapper. A default will always be created, even if no element exists.
         BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse(
                 DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), pc);
-        RootBeanDefinition rememberMeFilter = createRememberMeFilter(element, pc);
+        RootBeanDefinition rememberMeFilter = createRememberMeFilter(element, pc, authenticationManager);
         BeanDefinition anonFilter = createAnonymousFilter(element, pc);
 
         BeanDefinition etf = createExceptionTranslationFilter(element, pc, allowSessionCreation);
         RootBeanDefinition sfpf = createSessionFixationProtectionFilter(pc, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
                 sessionRegistryRef);
-        BeanDefinition fsi = createFilterSecurityInterceptor(element, pc, matcher, convertPathsToLowerCase);
+        BeanDefinition fsi = createFilterSecurityInterceptor(element, pc, matcher, convertPathsToLowerCase, authenticationManager);
 
         String portMapperName = pc.getReaderContext().registerWithGeneratedName(portMapper);
         if (channelRequestMap.size() > 0) {
@@ -204,9 +216,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER, sfpf);
         }
 
-        final FilterAndEntryPoint basic = createBasicFilter(element, pc, autoConfig);
-        final FilterAndEntryPoint form = createFormLoginFilter(element, pc, autoConfig, allowSessionCreation, sfpf);
-        final FilterAndEntryPoint openID = createOpenIDLoginFilter(element, pc, autoConfig, allowSessionCreation, sfpf);
+        final FilterAndEntryPoint basic = createBasicFilter(element, pc, autoConfig, authenticationManager);
+        final FilterAndEntryPoint form = createFormLoginFilter(element, pc, autoConfig, allowSessionCreation,
+                sfpf, authenticationManager);
+        final FilterAndEntryPoint openID = createOpenIDLoginFilter(element, pc, autoConfig, allowSessionCreation,
+                sfpf, authenticationManager);
 
         String rememberMeServicesId = null;
         if (rememberMeFilter != null) {
@@ -233,7 +247,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             injectSessionRegistryRef(openID.filter, sessionRegistryRef);
         }
 
-        FilterAndEntryPoint x509 = createX509Filter(element, pc);
+        String x509ProviderId = null;
+        FilterAndEntryPoint x509 = createX509Filter(element, pc, authenticationManager);
 
         BeanMetadataElement entryPoint = selectEntryPoint(element, pc, basic, form, openID, x509);
         etf.getPropertyValues().addPropertyValue("authenticationEntryPoint", entryPoint);
@@ -256,6 +271,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
         if (x509.filter != null) {
             unorderedFilterChain.add(new OrderDecorator(x509.filter, X509_FILTER));
+            BeanReference x509Provider = createX509Provider(element, pc);
+            x509ProviderId = x509Provider.getBeanName();
+            authenticationProviders.add(x509Provider);
         }
 
         if (form.filter != null) {
@@ -264,6 +282,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
         if (openID.filter != null) {
             unorderedFilterChain.add(new OrderDecorator(openID.filter, OPENID_PROCESSING_FILTER));
+            authenticationProviders.add(createOpenIDProvider(element, pc));
         }
 
         if (loginPageGenerationFilter != null) {
@@ -280,10 +299,12 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
         if (rememberMeFilter != null) {
             unorderedFilterChain.add(new OrderDecorator(rememberMeFilter, REMEMBER_ME_FILTER));
+            authenticationProviders.add(createRememberMeProvider(rememberMeFilter, pc, rememberMeServicesId));
         }
 
         if (anonFilter != null) {
             unorderedFilterChain.add(new OrderDecorator(anonFilter, ANONYMOUS_FILTER));
+            authenticationProviders.add(createAnonymousProvider(anonFilter, pc));
         }
 
         unorderedFilterChain.add(new OrderDecorator(etf, EXCEPTION_TRANSLATION_FILTER));
@@ -313,7 +334,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         registerFilterChainProxy(pc, filterChainMap, matcher, source);
 
         BeanDefinitionBuilder userServiceInjector = BeanDefinitionBuilder.rootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
-        userServiceInjector.addConstructorArgValue(BeanIds.X509_AUTH_PROVIDER);
+        userServiceInjector.addConstructorArgValue(x509ProviderId);
         userServiceInjector.addConstructorArgValue(rememberMeServicesId);
         userServiceInjector.addConstructorArgValue(rememberMeServicesId);
         userServiceInjector.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
@@ -323,6 +344,28 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         return null;
     }
 
+    /**
+     * Creates the internal AuthentiationManager bean which uses the externally registered (global) one as
+     * a parent.
+     *
+     * All the providers registered by this &lt;http&gt; block will be registered with the internal
+     * authentication manager, along with the ConcurrentSessionController (if necessary).
+     */
+    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("providers", authenticationProviders);
+
+        if (concurrencyController != null) {
+            authManager.addPropertyValue("sessionController", concurrencyController);
+        }
+        authManager.getRawBeanDefinition().setSource(pc.extractSource(element));
+        String id = pc.getReaderContext().registerWithGeneratedName(authManager.getBeanDefinition());
+
+        return new RuntimeBeanReference(id);
+    }
+
     private void injectRememberMeServicesRef(RootBeanDefinition bean, String rememberMeServicesId) {
         if (rememberMeServicesId != null) {
             bean.getPropertyValues().addPropertyValue("rememberMeServices", new RuntimeBeanReference(rememberMeServicesId));
@@ -367,6 +410,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         public int getOrder() {
             return order;
         }
+
+        public String toString() {
+            return bean + ", order = " + order;
+        }
     }
 
     List<OrderDecorator> buildCustomFilterList(Element element, ParserContext pc) {
@@ -420,13 +467,13 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         String grantedAuthority = null;
         String username = null;
         String key = null;
-        Object source = null;
+        Object source = pc.extractSource(element);
 
-        if (element != null) {
+        if (anonymousElt != null) {
             grantedAuthority = element.getAttribute("granted-authority");
             username = element.getAttribute("username");
             key = element.getAttribute("key");
-            source = pc.extractSource(element);
+            source = pc.extractSource(anonymousElt);
         }
 
         if (!StringUtils.hasText(grantedAuthority)) {
@@ -449,17 +496,21 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         filter.getPropertyValues().addPropertyValue("userAttribute", username + "," + grantedAuthority);
         filter.getPropertyValues().addPropertyValue(keyPV);
 
-        RootBeanDefinition provider = new RootBeanDefinition(AnonymousAuthenticationProvider.class);
-        provider.setSource(source);
-        provider.getPropertyValues().addPropertyValue(keyPV);
+        return filter;
+    }
 
-        pc.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER, provider);
-        ConfigUtils.addAuthenticationProvider(pc, BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER, element);
+    private BeanReference createAnonymousProvider(BeanDefinition anonFilter, ParserContext pc) {
+        RootBeanDefinition provider = new RootBeanDefinition(AnonymousAuthenticationProvider.class);
+        provider.setSource(anonFilter.getSource());
+        provider.getPropertyValues().addPropertyValue(anonFilter.getPropertyValues().getPropertyValue("key"));
+        String id = pc.getReaderContext().registerWithGeneratedName(provider);
+        pc.registerBeanComponent(new BeanComponentDefinition(provider, id));
 
-        return filter;
+        return new RuntimeBeanReference(id);
     }
 
-    private FilterAndEntryPoint createBasicFilter(Element elt, ParserContext pc, boolean autoConfig) {
+    private FilterAndEntryPoint createBasicFilter(Element elt, ParserContext pc,
+            boolean autoConfig, BeanReference authManager) {
         Element basicAuthElt = DomUtils.getChildElementByTagName(elt, Elements.BASIC_AUTH);
 
         String realm = elt.getAttribute(ATT_REALM);
@@ -477,23 +528,35 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
             entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
 
-            pc.getRegistry().registerBeanDefinition(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, entryPoint);
+            String entryPointId = pc.getReaderContext().registerWithGeneratedName(entryPoint);
 
-            filterBuilder.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
-            filterBuilder.addPropertyValue("authenticationEntryPoint", new RuntimeBeanReference(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT));
+            filterBuilder.addPropertyValue("authenticationManager", authManager);
+            filterBuilder.addPropertyValue("authenticationEntryPoint", new RuntimeBeanReference(entryPointId));
             filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
         }
 
         return new FilterAndEntryPoint(filter, entryPoint);
     }
 
-    private FilterAndEntryPoint createX509Filter(Element elt, ParserContext pc) {
+    private FilterAndEntryPoint createX509Filter(Element elt, ParserContext pc, BeanReference authManager) {
         Element x509Elt = DomUtils.getChildElementByTagName(elt, Elements.X509);
         RootBeanDefinition filter = null;
         RootBeanDefinition entryPoint = null;
 
         if (x509Elt != null) {
-            filter = new X509BeanDefinitionParser().parse(x509Elt, pc);
+            BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(X509PreAuthenticatedProcessingFilter.class);
+            filterBuilder.getRawBeanDefinition().setSource(pc.extractSource(x509Elt));
+            filterBuilder.addPropertyValue("authenticationManager", authManager);
+
+            String regex = x509Elt.getAttribute("subject-principal-regex");
+
+            if (StringUtils.hasText(regex)) {
+                SubjectDnX509PrincipalExtractor extractor = new SubjectDnX509PrincipalExtractor();
+                extractor.setSubjectDnRegex(regex);
+
+                filterBuilder.addPropertyValue("principalExtractor", extractor);
+            }
+            filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
             entryPoint = new RootBeanDefinition(Http403ForbiddenEntryPoint.class);
             entryPoint.setSource(pc.extractSource(x509Elt));
         }
@@ -501,6 +564,23 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         return new FilterAndEntryPoint(filter, entryPoint);
     }
 
+    private BeanReference createX509Provider(Element elt, ParserContext pc) {
+        Element x509Elt = DomUtils.getChildElementByTagName(elt, Elements.X509);
+        BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
+
+        String userServiceRef = x509Elt.getAttribute(ATT_USER_SERVICE_REF);
+
+        if (StringUtils.hasText(userServiceRef)) {
+            RootBeanDefinition preAuthUserService = new RootBeanDefinition(UserDetailsByNameServiceWrapper.class);
+            preAuthUserService.setSource(pc.extractSource(x509Elt));
+            preAuthUserService.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef));
+            provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", preAuthUserService);
+        }
+
+        String id = pc.getReaderContext().registerWithGeneratedName(provider);
+        return new RuntimeBeanReference(id);
+    }
+
     private BeanDefinition createLogoutFilter(Element elt, boolean autoConfig, ParserContext pc, String rememberMeServicesId) {
         Element logoutElt = DomUtils.getChildElementByTagName(elt, Elements.LOGOUT);
         if (logoutElt != null || autoConfig) {
@@ -511,17 +591,42 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         return null;
     }
 
-    private RootBeanDefinition createRememberMeFilter(Element elt, ParserContext pc) {
+    private RootBeanDefinition createRememberMeFilter(Element elt, ParserContext pc, BeanReference authenticationManager) {
         // Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
         Element rememberMeElt = DomUtils.getChildElementByTagName(elt, Elements.REMEMBER_ME);
 
         if (rememberMeElt != null) {
-            return (RootBeanDefinition) new RememberMeBeanDefinitionParser().parse(rememberMeElt, pc);
+            RootBeanDefinition filter = (RootBeanDefinition) new RememberMeBeanDefinitionParser().parse(rememberMeElt, pc);
+            filter.getPropertyValues().addPropertyValue("authenticationManager", authenticationManager);
+            return filter;
         }
 
         return null;
     }
 
+    private BeanReference createRememberMeProvider(BeanDefinition filter, ParserContext pc, String servicesId) {
+        RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class);
+        provider.setSource(filter.getSource());
+        // Locate the RememberMeServices bean and read the "key" property from it
+        PropertyValue key = null;
+        if (pc.getRegistry().containsBeanDefinition(servicesId)) {
+            BeanDefinition services = pc.getRegistry().getBeanDefinition(servicesId);
+
+            key = services.getPropertyValues().getPropertyValue("key");
+        }
+
+        if (key == null) {
+            key = new PropertyValue("key", RememberMeBeanDefinitionParser.DEF_KEY);
+        }
+
+        provider.getPropertyValues().addPropertyValue(key);
+
+        String id = pc.getReaderContext().registerWithGeneratedName(provider);
+        pc.registerBeanComponent(new BeanComponentDefinition(provider, id));
+
+        return new RuntimeBeanReference(id);
+    }
+
     private void registerFilterChainProxy(ParserContext pc, Map<String, List<BeanMetadataElement>> filterChainMap, UrlMatcher matcher, Object source) {
         if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
             pc.getReaderContext().error("Duplicate <http> element detected", source);
@@ -602,6 +707,32 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         return sessionControlFilter;
     }
 
+    private BeanReference createConcurrentSessionController(Element elt, BeanDefinition filter, BeanReference sessionRegistry, ParserContext pc) {
+        BeanDefinitionBuilder controllerBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionControllerImpl.class);
+        Element sessionCtrlElement = DomUtils.getChildElementByTagName(elt, Elements.CONCURRENT_SESSIONS);
+        controllerBuilder.getRawBeanDefinition().setSource(filter.getSource());
+        controllerBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+        controllerBuilder.addPropertyValue("sessionRegistry", sessionRegistry);
+
+        String maxSessions = sessionCtrlElement.getAttribute("max-sessions");
+
+        if (StringUtils.hasText(maxSessions)) {
+            controllerBuilder.addPropertyValue("maximumSessions", maxSessions);
+        }
+
+        String exceptionIfMaximumExceeded = sessionCtrlElement.getAttribute("exception-if-maximum-exceeded");
+
+        if (StringUtils.hasText(exceptionIfMaximumExceeded)) {
+            controllerBuilder.addPropertyValue("exceptionIfMaximumExceeded", exceptionIfMaximumExceeded);
+        }
+
+        BeanDefinition controller = controllerBuilder.getBeanDefinition();
+
+        String id = pc.getReaderContext().registerWithGeneratedName(controller);
+        pc.registerComponent(new BeanComponentDefinition(controller, id));
+        return new RuntimeBeanReference(id);
+    }
+
     private BeanDefinition createExceptionTranslationFilter(Element element, ParserContext pc, boolean allowSessionCreation) {
         BeanDefinitionBuilder exceptionTranslationFilterBuilder
             = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
@@ -649,7 +780,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
     }
 
     @SuppressWarnings("unchecked")
-    private BeanDefinition createFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher, boolean convertPathsToLowerCase) {
+    private BeanDefinition createFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher,
+            boolean convertPathsToLowerCase, BeanReference authManager) {
         BeanDefinitionBuilder fidsBuilder;
 
         boolean useExpressions = "true".equals(element.getAttribute(ATT_USE_EXPRESSIONS));
@@ -699,7 +831,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
 
         builder.addPropertyReference("accessDecisionManager", accessManagerId);
-        builder.addPropertyReference("authenticationManager", BeanIds.AUTHENTICATION_MANAGER);
+        builder.addPropertyValue("authenticationManager", authManager);
 
         if ("false".equals(element.getAttribute(ATT_ONCE_PER_REQUEST))) {
             builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE);
@@ -712,8 +844,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
     private BeanDefinition createChannelProcessingFilter(ParserContext pc, UrlMatcher matcher,
             LinkedHashMap<RequestKey, List<ConfigAttribute>> channelRequestMap, String portMapperBeanName) {
         RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
-        channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager",
-                new RuntimeBeanReference(BeanIds.CHANNEL_DECISION_MANAGER));
+
         DefaultFilterInvocationSecurityMetadataSource channelFilterInvDefSource =
             new DefaultFilterInvocationSecurityMetadataSource(matcher, channelRequestMap);
         channelFilterInvDefSource.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
@@ -734,7 +865,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         channelProcessors.add(inSecureChannelProcessor);
         channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", channelProcessors);
 
-        pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager);
+        String id = pc.getReaderContext().registerWithGeneratedName(channelDecisionManager);
+        channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager", new RuntimeBeanReference(id));
         return channelFilter;
     }
 
@@ -757,7 +889,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         return null;
     }
 
-    private FilterAndEntryPoint createFormLoginFilter(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation, RootBeanDefinition sfpf) {
+    private FilterAndEntryPoint createFormLoginFilter(Element element, ParserContext pc, boolean autoConfig,
+            boolean allowSessionCreation, RootBeanDefinition sfpf, BeanReference authManager) {
         RootBeanDefinition formLoginFilter = null;
         RootBeanDefinition formLoginEntryPoint = null;
 
@@ -774,12 +907,14 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
         if (formLoginFilter != null) {
             formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
+            formLoginFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
         }
 
         return new FilterAndEntryPoint(formLoginFilter, formLoginEntryPoint);
     }
 
-    private FilterAndEntryPoint createOpenIDLoginFilter(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation, RootBeanDefinition sfpf) {
+    private FilterAndEntryPoint createOpenIDLoginFilter(Element element, ParserContext pc, boolean autoConfig,
+            boolean allowSessionCreation, RootBeanDefinition sfpf, BeanReference authManager) {
         Element openIDLoginElt = DomUtils.getChildElementByTagName(element, Elements.OPENID_LOGIN);
         RootBeanDefinition openIDFilter = null;
         RootBeanDefinition openIDEntryPoint = null;
@@ -791,28 +926,32 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             parser.parse(openIDLoginElt, pc, sfpf);
             openIDFilter = parser.getFilterBean();
             openIDEntryPoint = parser.getEntryPointBean();
-
-            BeanDefinitionBuilder openIDProviderBuilder =
-                BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_AUTHENTICATION_PROVIDER_CLASS);
-
-            String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
-
-            if (StringUtils.hasText(userService)) {
-                openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
-            }
-
-            BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
-            pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider);
-            ConfigUtils.addAuthenticationProvider(pc, BeanIds.OPEN_ID_PROVIDER, element);
         }
 
         if (openIDFilter != null) {
             openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
+            openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
         }
 
         return new FilterAndEntryPoint(openIDFilter, openIDEntryPoint);
     }
 
+    private BeanReference createOpenIDProvider(Element elt, ParserContext pc) {
+        Element openIDLoginElt = DomUtils.getChildElementByTagName(elt, Elements.OPENID_LOGIN);
+        BeanDefinitionBuilder openIDProviderBuilder =
+            BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_AUTHENTICATION_PROVIDER_CLASS);
+
+        String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
+
+        if (StringUtils.hasText(userService)) {
+            openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
+        }
+
+        BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
+        String id = pc.getReaderContext().registerWithGeneratedName(openIDProvider);
+        return new RuntimeBeanReference(id);
+    }
+
     class FilterAndEntryPoint {
         RootBeanDefinition filter;
         RootBeanDefinition entryPoint;

+ 0 - 12
config/src/main/java/org/springframework/security/config/RememberMeBeanDefinitionParser.java

@@ -14,7 +14,6 @@ import org.springframework.security.web.authentication.rememberme.JdbcTokenRepos
 import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
 import org.springframework.security.web.authentication.rememberme.RememberMeProcessingFilter;
 import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
-import org.springframework.security.authentication.RememberMeAuthenticationProvider;
 import org.springframework.util.StringUtils;
 import org.w3c.dom.Element;
 
@@ -115,26 +114,15 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
             pc.getRegistry().registerAlias(servicesName, element.getAttribute(ATT_SERVICES_ALIAS));
         }
 
-        RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class);
-        provider.setSource(source);
-        provider.getPropertyValues().addPropertyValue(ATT_KEY, key);
-        pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER, provider);
-        ConfigUtils.addAuthenticationProvider(pc, BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER, element);
-
         BeanDefinition filter = createFilter(pc, source);
         pc.popAndRegisterContainingComponent();
 
         return filter;
     }
 
-    String getServicesName() {
-        return servicesName;
-    }
-
     private BeanDefinition createFilter(ParserContext pc, Object source) {
         BeanDefinitionBuilder filter = BeanDefinitionBuilder.rootBeanDefinition(RememberMeProcessingFilter.class);
         filter.getRawBeanDefinition().setSource(source);
-        filter.addPropertyReference("authenticationManager", BeanIds.AUTHENTICATION_MANAGER);
         filter.addPropertyReference("rememberMeServices", servicesName);
 
         return filter.getBeanDefinition();

+ 0 - 61
config/src/main/java/org/springframework/security/config/X509BeanDefinitionParser.java

@@ -1,61 +0,0 @@
-package org.springframework.security.config;
-
-import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
-import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
-import org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor;
-import org.springframework.security.web.authentication.preauth.x509.X509PreAuthenticatedProcessingFilter;
-import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
-import org.springframework.beans.factory.xml.BeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.util.StringUtils;
-
-import org.w3c.dom.Element;
-
-/**
- * Parses x509 element in namespace, registering an {@link X509PreAuthenticatedProcessingFilter} instance and a
- * {@link Http403ForbiddenEntryPoint}.
- *
- * @author Luke Taylor
- * @version $Id$
- * @since 2.0
- */
-public class X509BeanDefinitionParser implements BeanDefinitionParser {
-    public static final String ATT_REGEX = "subject-principal-regex";
-    public static final String ATT_USER_SERVICE_REF = "user-service-ref";
-
-    public RootBeanDefinition parse(Element element, ParserContext parserContext) {
-        BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(X509PreAuthenticatedProcessingFilter.class);
-        Object source = parserContext.extractSource(element);
-        filterBuilder.getRawBeanDefinition().setSource(source);
-
-        String regex = element.getAttribute(ATT_REGEX);
-
-        if (StringUtils.hasText(regex)) {
-            SubjectDnX509PrincipalExtractor extractor = new SubjectDnX509PrincipalExtractor();
-            extractor.setSubjectDnRegex(regex);
-
-            filterBuilder.addPropertyValue("principalExtractor", extractor);
-        }
-
-        BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
-        parserContext.getRegistry().registerBeanDefinition(BeanIds.X509_AUTH_PROVIDER, provider);
-        ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.X509_AUTH_PROVIDER, element);
-
-        String userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
-
-        if (StringUtils.hasText(userServiceRef)) {
-            RootBeanDefinition preAuthUserService = new RootBeanDefinition(UserDetailsByNameServiceWrapper.class);
-            preAuthUserService.setSource(source);
-            preAuthUserService.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef));
-            provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", preAuthUserService);
-        }
-
-        filterBuilder.addPropertyReference("authenticationManager", BeanIds.AUTHENTICATION_MANAGER);
-
-        return (RootBeanDefinition) filterBuilder.getBeanDefinition();
-    }
-}

+ 1 - 0
config/src/test/java/org/springframework/security/config/FilterSecurityMetadataSourceBeanDefinitionParserTests.java

@@ -67,6 +67,7 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
                 "           <intercept-url pattern='/**' access='ROLE_USER'/>" +
                 "       </filter-security-metadata-source>" +
                 "   </b:property>" +
+                "   <b:property name='authenticationManager' ref='" + BeanIds.AUTHENTICATION_MANAGER +"'/>"+
                 "</b:bean>" + ConfigTestUtils.AUTH_PROVIDER_XML);
 
 

+ 18 - 6
config/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java

@@ -28,6 +28,7 @@ import org.springframework.security.access.SecurityConfig;
 import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.authentication.concurrent.ConcurrentLoginException;
+import org.springframework.security.authentication.concurrent.ConcurrentSessionController;
 import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl;
 import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
 import org.springframework.security.config.util.InMemoryXmlApplicationContext;
@@ -565,7 +566,7 @@ public class HttpSecurityBeanDefinitionParserTests {
 
         assertTrue(filters.get(0) instanceof ConcurrentSessionFilter);
         assertNotNull(appContext.getBean("seshRegistry"));
-        assertNotNull(appContext.getBean(BeanIds.CONCURRENT_SESSION_CONTROLLER));
+        assertNotNull(getConcurrentSessionController());
     }
 
     @Test
@@ -581,8 +582,7 @@ public class HttpSecurityBeanDefinitionParserTests {
                 getFilter(ConcurrentSessionFilter.class),"sessionRegistry");
         Object sessionRegistryFromFormLoginFilter = FieldUtils.getFieldValue(
                 getFilter(UsernamePasswordAuthenticationProcessingFilter.class),"sessionRegistry");
-        Object sessionRegistryFromController = FieldUtils.getFieldValue(
-                appContext.getBean(BeanIds.CONCURRENT_SESSION_CONTROLLER),"sessionRegistry");
+        Object sessionRegistryFromController = FieldUtils.getFieldValue(getConcurrentSessionController(),"sessionRegistry");
         Object sessionRegistryFromFixationFilter = FieldUtils.getFieldValue(
                 getFilter(SessionFixationProtectionFilter.class),"sessionRegistry");
 
@@ -592,7 +592,9 @@ public class HttpSecurityBeanDefinitionParserTests {
         // SEC-1143
         assertSame(sessionRegistry, sessionRegistryFromFormLoginFilter);
     }
-
+/*
+// These no longer apply with the internal authentication manager in <http> and it won't be possible to check the
+// Validity of the configuration against the central AuthenticationManager when we allow more than one <http> element.
     @Test(expected=BeanDefinitionParsingException.class)
     public void concurrentSessionSupportCantBeUsedWithIndependentControllerBean() throws Exception {
         setContext(
@@ -620,14 +622,14 @@ public class HttpSecurityBeanDefinitionParserTests {
                 "</b:bean>" +
                 "<authentication-manager alias='authManager' session-controller-ref='sc'/>" + AUTH_PROVIDER_XML);
     }
-
+*/
     @Test(expected=ConcurrentLoginException.class)
     public void concurrentSessionMaxSessionsIsCorrectlyConfigured() throws Exception {
         setContext(
                 "<http auto-config='true'>" +
                 "    <concurrent-session-control max-sessions='2' exception-if-maximum-exceeded='true' />" +
                 "</http>"  + AUTH_PROVIDER_XML);
-        ConcurrentSessionControllerImpl seshController = (ConcurrentSessionControllerImpl) appContext.getBean(BeanIds.CONCURRENT_SESSION_CONTROLLER);
+        ConcurrentSessionControllerImpl seshController = (ConcurrentSessionControllerImpl) getConcurrentSessionController();
         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("bob", "pass");
         // Register 2 sessions and then check a third
         MockHttpServletRequest req = new MockHttpServletRequest();
@@ -919,4 +921,14 @@ public class HttpSecurityBeanDefinitionParserTests {
         return ((RememberMeProcessingFilter)getFilter(RememberMeProcessingFilter.class)).getRememberMeServices();
     }
 
+    @SuppressWarnings("unchecked")
+    private ConcurrentSessionController getConcurrentSessionController() {
+        Map beans = appContext.getBeansOfType(ConcurrentSessionController.class);
+
+        if (beans.size() == 0) {
+            return null;
+        }
+        return (ConcurrentSessionController) new ArrayList(beans.values()).get(0);
+    }
+
 }

+ 12 - 4
core/src/main/java/org/springframework/security/authentication/ProviderManager.java

@@ -15,10 +15,12 @@
 
 package org.springframework.security.authentication;
 
+import java.util.Collections;
 import java.util.List;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.InitializingBean;
 import org.springframework.context.MessageSource;
 import org.springframework.context.MessageSourceAware;
 import org.springframework.context.support.MessageSourceAccessor;
@@ -69,7 +71,7 @@ import org.springframework.util.Assert;
  * @see ConcurrentSessionController
  * @see DefaultAuthenticationEventPublisher
  */
-public class ProviderManager extends AbstractAuthenticationManager implements MessageSourceAware {
+public class ProviderManager extends AbstractAuthenticationManager implements MessageSourceAware, InitializingBean {
     //~ Static fields/initializers =====================================================================================
 
     private static final Log logger = LogFactory.getLog(ProviderManager.class);
@@ -78,12 +80,19 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
 
     private AuthenticationEventPublisher eventPublisher = new NullEventPublisher();
     private ConcurrentSessionController sessionController = new NullConcurrentSessionController();
-    private List<AuthenticationProvider> providers;
+    private List<AuthenticationProvider> providers = Collections.emptyList();
     protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
     private AuthenticationManager parent;
 
     //~ Methods ========================================================================================================
 
+    public void afterPropertiesSet() throws Exception {
+        if (parent == null && providers.isEmpty()) {
+            throw new IllegalArgumentException("A parent AuthenticationManager or a list " +
+                    "of AuthenticationProviders is required");
+        }
+    }
+
     /**
      * Attempts to authenticate the passed {@link Authentication} object.
      * <p>
@@ -222,8 +231,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
      */
     @SuppressWarnings("unchecked")
     public void setProviders(List providers) {
-        Assert.notEmpty(providers, "A list of AuthenticationProviders is required");
-
+        Assert.notNull(providers);
         for(Object currentObject : providers) {
             Assert.isInstanceOf(AuthenticationProvider.class, currentObject, "Can only provide AuthenticationProvider instances");
         }

+ 2 - 3
core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java

@@ -110,10 +110,9 @@ public class ProviderManagerTests {
     }
 
     @Test(expected=IllegalArgumentException.class)
-    public void testStartupFailsIfProviderListNull() throws Exception {
+    public void testStartupFailsIfProvidersNotSet() throws Exception {
         ProviderManager mgr = new ProviderManager();
-
-        mgr.setProviders(null);
+        mgr.afterPropertiesSet();
     }
 
     @Test

+ 2 - 2
samples/tutorial/src/main/webapp/WEB-INF/applicationContext-security.xml

@@ -33,9 +33,9 @@
     Uncomment to enable X509 client authentication support
         <x509 />
 -->
-        <!-- Uncomment to limit the number of sessions a user can have
+        <!-- Uncomment to limit the number of sessions a user can have -->
         <concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true"/>
-        -->
+
     </http>
 
     <authentication-manager alias="authManager"/>