Browse Source

SEC-1186: Refactoring to bring all filter registrations into the HttpBDP parse method in preparation for building the filter chain and map at that point, rather than in a post-processor

Luke Taylor 16 years ago
parent
commit
074fa7d629

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

@@ -68,10 +68,6 @@ public class AnonymousBeanDefinitionParser implements BeanDefinitionParser {
         parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER, provider);
         ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER);
 
-        parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_PROCESSING_FILTER, filter);
-        ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.ANONYMOUS_PROCESSING_FILTER));
-        parserContext.registerComponent(new BeanComponentDefinition(filter, BeanIds.ANONYMOUS_PROCESSING_FILTER));
-
-        return null;
+        return filter;
     }
 }

+ 3 - 8
config/src/main/java/org/springframework/security/config/BasicAuthenticationBeanDefinitionParser.java

@@ -31,19 +31,14 @@ public class BasicAuthenticationBeanDefinitionParser implements BeanDefinitionPa
         RootBeanDefinition entryPoint = new RootBeanDefinition(BasicProcessingFilterEntryPoint.class);
         entryPoint.setSource(parserContext.extractSource(elt));
         entryPoint.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-        
+
         entryPoint.getPropertyValues().addPropertyValue("realmName", realmName);
-    
+
         parserContext.getRegistry().registerBeanDefinition(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, entryPoint);
 
         filterBuilder.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
         filterBuilder.addPropertyValue("authenticationEntryPoint", new RuntimeBeanReference(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT));
 
-        parserContext.getRegistry().registerBeanDefinition(BeanIds.BASIC_AUTHENTICATION_FILTER,
-                filterBuilder.getBeanDefinition());
-        ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.BASIC_AUTHENTICATION_FILTER));
-        parserContext.registerComponent(new BeanComponentDefinition(filterBuilder.getBeanDefinition(), 
-                BeanIds.BASIC_AUTHENTICATION_FILTER));
-        return null;
+        return filterBuilder.getBeanDefinition();
     }
 }

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

@@ -93,14 +93,10 @@ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionPar
 
         beanRegistry.registerBeanDefinition(BeanIds.CONCURRENT_SESSION_CONTROLLER, controller);
         parserContext.registerComponent(new BeanComponentDefinition(controller, BeanIds.CONCURRENT_SESSION_CONTROLLER));
-        beanRegistry.registerBeanDefinition(BeanIds.CONCURRENT_SESSION_FILTER, filterBuilder.getBeanDefinition());
-        parserContext.registerComponent(new BeanComponentDefinition(filterBuilder.getBeanDefinition(), BeanIds.CONCURRENT_SESSION_FILTER));
-        ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.CONCURRENT_SESSION_FILTER));
-
         ConfigUtils.setSessionControllerOnAuthenticationManager(parserContext, BeanIds.CONCURRENT_SESSION_CONTROLLER, element);
 
         parserContext.popAndRegisterContainingComponent();
 
-        return null;
+        return filterBuilder.getBeanDefinition();
     }
 }

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

@@ -8,6 +8,7 @@ import org.springframework.beans.MutablePropertyValues;
 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;
 import org.springframework.beans.factory.support.RootBeanDefinition;
@@ -116,6 +117,7 @@ abstract class ConfigUtils {
         RootBeanDefinition filterList = new RootBeanDefinition(FilterChainList.class);
         filterList.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_LIST, filterList);
+        pc.registerBeanComponent(new BeanComponentDefinition(filterList, BeanIds.FILTER_LIST));
     }
 
     @SuppressWarnings("unchecked")

+ 203 - 113
config/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java

@@ -9,11 +9,15 @@ import java.util.Map;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.springframework.beans.BeanMetadataElement;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.PropertyValues;
 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.BeanDefinitionRegistry;
 import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.support.ManagedMap;
 import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.beans.factory.xml.BeanDefinitionParser;
 import org.springframework.beans.factory.xml.ParserContext;
@@ -117,45 +121,60 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
     private static final String EXPRESSION_HANDLER_ID = "_webExpressionHandler";
 
     @SuppressWarnings("unchecked")
-    public BeanDefinition parse(Element element, ParserContext parserContext) {
-        ConfigUtils.registerProviderManagerIfNecessary(parserContext);
-        final BeanDefinitionRegistry registry = parserContext.getRegistry();
+    public BeanDefinition parse(Element element, ParserContext pc) {
+        ConfigUtils.registerProviderManagerIfNecessary(pc);
+        final BeanDefinitionRegistry registry = pc.getRegistry();
         final UrlMatcher matcher = createUrlMatcher(element);
-        final Object source = parserContext.extractSource(element);
+        final Object source = pc.extractSource(element);
         // SEC-501 - should paths stored in request maps be converted to lower case
         // true if Ant path and using lower case
         final boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
+        final boolean allowSessionCreation = !OPT_CREATE_SESSION_NEVER.equals(element.getAttribute(ATT_CREATE_SESSION));
 
         final List<Element> interceptUrlElts = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
-        final Map filterChainMap =  new LinkedHashMap();
+        final Map filterChainMap =  new ManagedMap();
         final LinkedHashMap channelRequestMap = new LinkedHashMap();
 
-        registerFilterChainProxy(parserContext, filterChainMap, matcher, source);
+        registerFilterChainProxy(pc, filterChainMap, matcher, source);
 
         // filterChainMap and channelRequestMap are populated by this call
-        parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
-                convertPathsToLowerCase, parserContext);
+        parseInterceptUrlsForChannelSecurityAndEmptyFilterChains(interceptUrlElts, filterChainMap, channelRequestMap,
+                convertPathsToLowerCase, pc);
 
-        boolean allowSessionCreation = registerSecurityContextPersistenceFilter(element, parserContext);
+        // Add the default filter list
+        List filterList = new ManagedList();
+        filterChainMap.put(matcher.getUniversalMatchPattern(), filterList);
 
-        registerServletApiFilter(element, parserContext);
+        BeanDefinition scpf = createSecurityContextPersistenceFilter(element, pc);
+        pc.getRegistry().registerBeanDefinition(BeanIds.SECURITY_CONTEXT_PERSISTENCE_FILTER, scpf);
+        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_PERSISTENCE_FILTER));
 
+        BeanDefinition servApiFilter = createServletApiFilter(element, pc);
+        if (servApiFilter != null) {
+	        pc.getRegistry().registerBeanDefinition(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER,servApiFilter);
+	        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER));
+        }
         // 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), parserContext);
+                DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), pc);
         registry.registerBeanDefinition(BeanIds.PORT_MAPPER, portMapper);
 
-        registerExceptionTranslationFilter(element, parserContext, allowSessionCreation);
+        BeanDefinition etf = createExceptionTranslationFilter(element, pc, allowSessionCreation);
+        pc.getRegistry().registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, etf);
+        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.EXCEPTION_TRANSLATION_FILTER));
 
         if (channelRequestMap.size() > 0) {
             // At least one channel requirement has been specified
-            registerChannelProcessingBeans(parserContext, matcher, channelRequestMap);
+            BeanDefinition cpf = createChannelProcessingFilter(pc, matcher, channelRequestMap);
+            pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, cpf);
+            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.CHANNEL_PROCESSING_FILTER));
+
         }
 
         boolean useExpressions = "true".equals(element.getAttribute(ATT_USE_EXPRESSIONS));
 
         LinkedHashMap<RequestKey, List<ConfigAttribute>> requestToAttributesMap =
-            parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, useExpressions, parserContext);
+            parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, useExpressions, pc);
 
         BeanDefinitionBuilder fidsBuilder;
         Class<? extends AccessDecisionVoter>[] voters;
@@ -167,7 +186,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             if (StringUtils.hasText(expressionHandlerRef)) {
                 logger.info("Using bean '" + expressionHandlerRef + "' as web SecurityExpressionHandler implementation");
             } else {
-                parserContext.getRegistry().registerBeanDefinition(EXPRESSION_HANDLER_ID,
+                pc.getRegistry().registerBeanDefinition(EXPRESSION_HANDLER_ID,
                         BeanDefinitionBuilder.rootBeanDefinition(EXPRESSION_HANDLER_CLASS).getBeanDefinition());
                 expressionHandlerRef = EXPRESSION_HANDLER_ID;
             }
@@ -189,35 +208,86 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
 
         if (!StringUtils.hasText(accessManagerId)) {
-            parserContext.getRegistry().registerBeanDefinition(BeanIds.WEB_ACCESS_MANAGER,
+            pc.getRegistry().registerBeanDefinition(BeanIds.WEB_ACCESS_MANAGER,
                         ConfigUtils.createAccessManagerBean(voters));
             accessManagerId = BeanIds.WEB_ACCESS_MANAGER;
         }
 
-        registerFilterSecurityInterceptor(element, parserContext, accessManagerId, fidsBuilder.getBeanDefinition());
+        BeanDefinition fsi = createFilterSecurityInterceptor(element, pc, accessManagerId, fidsBuilder.getBeanDefinition());
+        pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, fsi);
+        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR));
 
-        boolean sessionControlEnabled = registerConcurrentSessionControlBeansIfRequired(element, parserContext);
+        boolean sessionControlEnabled = false;
 
-        registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
-                sessionControlEnabled);
+        BeanDefinition concurrentSessionFilter = createConcurrentSessionFilterAndRelatedBeansIfRequired(element, pc);
+        if (concurrentSessionFilter != null) {
+        	sessionControlEnabled = true;
+	        pc.getRegistry().registerBeanDefinition(BeanIds.CONCURRENT_SESSION_FILTER, concurrentSessionFilter);
+	        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.CONCURRENT_SESSION_FILTER));
+        }
 
+        BeanDefinition sfpf = createSessionFixationProtectionFilter(pc, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
+                sessionControlEnabled);
+        if (sfpf != null) {
+        	pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER, sfpf);
+        	ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
+        }
         boolean autoConfig = "true".equals(element.getAttribute(ATT_AUTO_CONFIG));
 
         Element anonymousElt = DomUtils.getChildElementByTagName(element, Elements.ANONYMOUS);
 
         if (anonymousElt == null || !"false".equals(anonymousElt.getAttribute("enabled"))) {
-            new AnonymousBeanDefinitionParser().parse(anonymousElt, parserContext);
+        	BeanDefinition anonFilter = new AnonymousBeanDefinitionParser().parse(anonymousElt, pc);
+            pc.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_PROCESSING_FILTER, anonFilter);
+            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.ANONYMOUS_PROCESSING_FILTER));
         }
 
-        parseRememberMeAndLogout(element, autoConfig, parserContext);
+        parseRememberMeAndLogout(element, autoConfig, pc);
+
+        String realm = element.getAttribute(ATT_REALM);
+		if (!StringUtils.hasText(realm)) {
+		    realm = DEF_REALM;
+		}
+
+		final FilterAndEntryPoint form = createFormLoginFilter(element, pc, autoConfig, allowSessionCreation);
 
-        parseBasicFormLoginAndOpenID(element, parserContext, autoConfig, allowSessionCreation);
+		if (form.filter != null) {
+		    pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, form.filter);
+		    ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
+		    pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, form.entryPoint);
+		}
+
+		Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
+		if (basicAuthElt != null || autoConfig) {
+		    BeanDefinition basicFilter = new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc);
+	        pc.getRegistry().registerBeanDefinition(BeanIds.BASIC_AUTHENTICATION_FILTER, basicFilter);
+	        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.BASIC_AUTHENTICATION_FILTER));
+		}
+
+		FilterAndEntryPoint openID = createOpenIDLoginFilter(element, pc, autoConfig, allowSessionCreation);
+
+		if (openID.filter != null) {
+		    pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openID.filter);
+		    ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
+		    pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openID.entryPoint);
+		}
+
+		BeanDefinition loginPageGenerationFilter = createLoginPageFilterIfNeeded(form, openID);
+
+		if (loginPageGenerationFilter != null) {
+		    pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER, loginPageGenerationFilter);
+		    ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER));
+		}
 
         Element x509Elt = DomUtils.getChildElementByTagName(element, Elements.X509);
         if (x509Elt != null) {
-            new X509BeanDefinitionParser().parse(x509Elt, parserContext);
+            BeanDefinition x509Filter = new X509BeanDefinitionParser().parse(x509Elt, pc);
+            pc.getRegistry().registerBeanDefinition(BeanIds.X509_FILTER, x509Filter);
+            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.X509_FILTER));
         }
 
+		selectEntryPoint(element, pc, form, openID);
+
         // Register the post processors which will tie up the loose ends in the configuration once the app context has been created and all beans are available.
         RootBeanDefinition postProcessor = new RootBeanDefinition(EntryPointInjectionBeanPostProcessor.class);
         postProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
@@ -236,7 +306,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
         if (rememberMeElt != null) {
             RememberMeBeanDefinitionParser rmbdp = new RememberMeBeanDefinitionParser();
-            rmbdp.parse(rememberMeElt, pc);
+            BeanDefinition filter = rmbdp.parse(rememberMeElt, pc);
+            pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_FILTER, filter);
+            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.REMEMBER_ME_FILTER));
             rememberMeServices = rmbdp.getServicesName();
             // Post processor to inject RememberMeServices into filters which need it
             RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
@@ -246,7 +318,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
         Element logoutElt = DomUtils.getChildElementByTagName(elt, Elements.LOGOUT);
         if (logoutElt != null || autoConfig) {
-            new LogoutBeanDefinitionParser(rememberMeServices).parse(logoutElt, pc);
+            BeanDefinition logoutFilter = new LogoutBeanDefinitionParser(rememberMeServices).parse(logoutElt, pc);
+
+            pc.getRegistry().registerBeanDefinition(BeanIds.LOGOUT_FILTER, logoutFilter);
+            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.LOGOUT_FILTER));
         }
     }
 
@@ -256,18 +331,19 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             pc.getReaderContext().error("Duplicate <http> element detected", source);
         }
 
-        RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
-        filterChainProxy.setSource(source);
-        filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher);
-        filterChainProxy.getPropertyValues().addPropertyValue("stripQueryStringFromUrls", Boolean.valueOf(matcher instanceof AntUrlPathMatcher));
-        filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
-        pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
+        BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class);
+        fcpBldr.getRawBeanDefinition().setSource(source);
+        fcpBldr.addPropertyValue("matcher", matcher);
+        fcpBldr.addPropertyValue("stripQueryStringFromUrls", Boolean.valueOf(matcher instanceof AntUrlPathMatcher));
+        fcpBldr.addPropertyValue("filterChainMap", filterChainMap);
+        BeanDefinition fcpBean = fcpBldr.getBeanDefinition();
+        pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, fcpBean);
         pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
+        pc.registerBeanComponent(new BeanComponentDefinition(fcpBean,BeanIds.FILTER_CHAIN_PROXY));
     }
 
-    private boolean registerSecurityContextPersistenceFilter(Element element, ParserContext pc) {
+    private BeanDefinition createSecurityContextPersistenceFilter(Element element, ParserContext pc) {
         BeanDefinitionBuilder scpf = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextPersistenceFilter.class);
-        boolean sessionCreationAllowed = true;
 
         String repoRef = element.getAttribute(ATT_SECURITY_CONTEXT_REPOSITORY);
         String createSession = element.getAttribute(ATT_CREATE_SESSION);
@@ -291,7 +367,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             } else if (OPT_CREATE_SESSION_NEVER.equals(createSession)) {
                 contextRepo.addPropertyValue("allowSessionCreation", Boolean.FALSE);
                 scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
-                sessionCreationAllowed = false;
             } else {
                 createSession = DEF_CREATE_SESSION_IF_REQUIRED;
                 contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE);
@@ -305,47 +380,43 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             scpf.addPropertyValue("securityContextRepository", contextRepo.getBeanDefinition());
         }
 
-        pc.getRegistry().registerBeanDefinition(BeanIds.SECURITY_CONTEXT_PERSISTENCE_FILTER, scpf.getBeanDefinition());
-        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_PERSISTENCE_FILTER));
-
-        return sessionCreationAllowed;
+        return scpf.getBeanDefinition();
     }
 
     // Adds the servlet-api integration filter if required
-    private void registerServletApiFilter(Element element, ParserContext pc) {
+    private RootBeanDefinition createServletApiFilter(Element element, ParserContext pc) {
         String provideServletApi = element.getAttribute(ATT_SERVLET_API_PROVISION);
         if (!StringUtils.hasText(provideServletApi)) {
             provideServletApi = DEF_SERVLET_API_PROVISION;
         }
 
         if ("true".equals(provideServletApi)) {
-            pc.getRegistry().registerBeanDefinition(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER,
-                    new RootBeanDefinition(SecurityContextHolderAwareRequestFilter.class));
-            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER));
+        	return new RootBeanDefinition(SecurityContextHolderAwareRequestFilter.class);
         }
+        return null;
     }
 
-    private boolean registerConcurrentSessionControlBeansIfRequired(Element element, ParserContext parserContext) {
+    private BeanDefinition createConcurrentSessionFilterAndRelatedBeansIfRequired(Element element, ParserContext parserContext) {
         Element sessionControlElt = DomUtils.getChildElementByTagName(element, Elements.CONCURRENT_SESSIONS);
         if (sessionControlElt == null) {
-            return false;
+            return null;
         }
 
-        new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext);
+        BeanDefinition sessionControlFilter = new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext);
         logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true");
         BeanDefinition sessionIntegrationFilter = parserContext.getRegistry().getBeanDefinition(BeanIds.SECURITY_CONTEXT_PERSISTENCE_FILTER);
         sessionIntegrationFilter.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
-        return true;
+        return sessionControlFilter;
     }
 
-    private void registerExceptionTranslationFilter(Element element, ParserContext pc, boolean allowSessionCreation) {
+    private BeanDefinition createExceptionTranslationFilter(Element element, ParserContext pc, boolean allowSessionCreation) {
         BeanDefinitionBuilder exceptionTranslationFilterBuilder
             = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
         exceptionTranslationFilterBuilder.addPropertyValue("createSessionAllowed", Boolean.valueOf(allowSessionCreation));
         exceptionTranslationFilterBuilder.addPropertyValue("accessDeniedHandler", createAccessDeniedHandler(element, pc));
 
-        pc.getRegistry().registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition());
-        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.EXCEPTION_TRANSLATION_FILTER));
+
+        return exceptionTranslationFilterBuilder.getBeanDefinition();
     }
 
     private BeanMetadataElement createAccessDeniedHandler(Element element, ParserContext pc) {
@@ -384,7 +455,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         return accessDeniedHandler.getBeanDefinition();
     }
 
-    private void registerFilterSecurityInterceptor(Element element, ParserContext pc, String accessManagerId,
+    private BeanDefinition createFilterSecurityInterceptor(Element element, ParserContext pc, String accessManagerId,
             BeanDefinition fids) {
         BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
 
@@ -396,12 +467,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         }
 
         builder.addPropertyValue("securityMetadataSource", fids);
-        pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition());
-        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR));
+        return builder.getBeanDefinition();
     }
 
     @SuppressWarnings("unchecked")
-    private void registerChannelProcessingBeans(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) {
+    private BeanDefinition createChannelProcessingFilter(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) {
         RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
         channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager",
                 new RuntimeBeanReference(BeanIds.CHANNEL_DECISION_MANAGER));
@@ -425,13 +495,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         channelProcessors.add(inSecureChannelProcessor);
         channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", channelProcessors);
 
-        pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter);
-        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.CHANNEL_PROCESSING_FILTER));
         pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager);
-
+        return channelFilter;
     }
 
-    private void registerSessionFixationProtectionFilter(ParserContext pc, String sessionFixationAttribute, boolean sessionControlEnabled) {
+    private BeanDefinition createSessionFixationProtectionFilter(ParserContext pc, String sessionFixationAttribute, boolean sessionControlEnabled) {
         if(!StringUtils.hasText(sessionFixationAttribute)) {
             sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION;
         }
@@ -444,29 +512,14 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             if (sessionControlEnabled) {
                 sessionFixationFilter.addPropertyReference("sessionRegistry", BeanIds.SESSION_REGISTRY);
             }
-            pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER,
-                    sessionFixationFilter.getBeanDefinition());
-            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
+            return sessionFixationFilter.getBeanDefinition();
         }
+        return null;
     }
 
-    private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation) {
+    private FilterAndEntryPoint createFormLoginFilter(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation) {
         RootBeanDefinition formLoginFilter = null;
         RootBeanDefinition formLoginEntryPoint = null;
-        String formLoginPage = null;
-        RootBeanDefinition openIDFilter = null;
-        RootBeanDefinition openIDEntryPoint = null;
-        String openIDLoginPage = null;
-
-        String realm = element.getAttribute(ATT_REALM);
-        if (!StringUtils.hasText(realm)) {
-            realm = DEF_REALM;
-        }
-
-        Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
-        if (basicAuthElt != null || autoConfig) {
-            new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc);
-        }
 
         Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
 
@@ -477,10 +530,19 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             parser.parse(formLoginElt, pc);
             formLoginFilter = parser.getFilterBean();
             formLoginEntryPoint = parser.getEntryPointBean();
-            formLoginPage = parser.getLoginPage();
         }
 
+        if (formLoginFilter != null) {
+            formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
+        }
+
+        return new FilterAndEntryPoint(formLoginFilter, formLoginEntryPoint);
+    }
+
+    private FilterAndEntryPoint createOpenIDLoginFilter(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation) {
         Element openIDLoginElt = DomUtils.getChildElementByTagName(element, Elements.OPENID_LOGIN);
+        RootBeanDefinition openIDFilter = null;
+        RootBeanDefinition openIDEntryPoint = null;
 
         if (openIDLoginElt != null) {
             FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
@@ -489,7 +551,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             parser.parse(openIDLoginElt, pc);
             openIDFilter = parser.getFilterBean();
             openIDEntryPoint = parser.getEntryPointBean();
-            openIDLoginPage = parser.getLoginPage();
 
             BeanDefinitionBuilder openIDProviderBuilder =
                 BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_AUTHENTICATION_PROVIDER_CLASS);
@@ -505,44 +566,24 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             ConfigUtils.addAuthenticationProvider(pc, BeanIds.OPEN_ID_PROVIDER);
         }
 
-        boolean needLoginPage = false;
-
-        if (formLoginFilter != null) {
-            needLoginPage = true;
-            formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
-            pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter);
-            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
-            pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint);
-        }
-
         if (openIDFilter != null) {
-            needLoginPage = true;
             openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
-            pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter);
-            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
-            pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint);
         }
 
-        // If no login page has been defined, add in the default page generator.
-        if (needLoginPage && formLoginPage == null && openIDLoginPage == null) {
-            logger.info("No login page configured. The default internal one will be used. Use the '"
-                     + FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page.");
-            BeanDefinitionBuilder loginPageFilter =
-                BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
+        return new FilterAndEntryPoint(openIDFilter, openIDEntryPoint);
+    }
 
-            if (formLoginFilter != null) {
-                loginPageFilter.addConstructorArgValue(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
-            }
+    class FilterAndEntryPoint {
+        RootBeanDefinition filter;
+    	RootBeanDefinition entryPoint;
 
-            if (openIDFilter != null) {
-                loginPageFilter.addConstructorArgValue(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
-            }
-
-            pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER,
-                    loginPageFilter.getBeanDefinition());
-            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER));
-        }
+		public FilterAndEntryPoint(RootBeanDefinition filter, RootBeanDefinition entryPoint) {
+			this.filter = filter;
+			this.entryPoint = entryPoint;
+		}
+    }
 
+    private void selectEntryPoint(Element element, ParserContext pc, FilterAndEntryPoint form, FilterAndEntryPoint openID) {
         // We need to establish the main entry point.
         // First check if a custom entry point bean is set
         String customEntryPoint = element.getAttribute(ATT_ENTRY_POINT_REF);
@@ -552,6 +593,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             return;
         }
 
+        Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
+        Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
+        Element openIDLoginElt = DomUtils.getChildElementByTagName(element, Elements.OPENID_LOGIN);
         // Basic takes precedence if explicit element is used and no others are configured
         if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null) {
             pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
@@ -560,13 +604,15 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
         // If formLogin has been enabled either through an element or auto-config, then it is used if no openID login page
         // has been set
-        if (formLoginFilter != null && openIDLoginPage == null) {
+        String openIDLoginPage = getLoginFormUrl(openID.entryPoint);
+
+        if (form.filter != null && openIDLoginPage == null) {
             pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
             return;
         }
 
         // Otherwise use OpenID if enabled
-        if (openIDFilter != null && formLoginFilter == null) {
+        if (openID.filter != null && form.filter == null) {
             pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
             return;
         }
@@ -579,10 +625,54 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
         pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " +
                 "make sure you have a login mechanism configured through the namespace (such as form-login) or " +
-                "specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attribute ",
+                "specify a custom AuthenticationEntryPoint with the '" + ATT_ENTRY_POINT_REF+ "' attribute ",
                 pc.extractSource(element));
     }
 
+    private String getLoginFormUrl(RootBeanDefinition entryPoint) {
+    	if (entryPoint == null) {
+    		return null;
+    	}
+
+    	PropertyValues pvs = entryPoint.getPropertyValues();
+    	PropertyValue pv = pvs.getPropertyValue("loginFormUrl");
+        if (pv == null) {
+        	 return null;
+        }
+
+        return (String) pv.getValue();
+    }
+
+
+    BeanDefinition createLoginPageFilterIfNeeded(FilterAndEntryPoint form, FilterAndEntryPoint openID) {
+        boolean needLoginPage = form.filter != null || openID.filter != null;
+        String formLoginPage = getLoginFormUrl(form.entryPoint);
+        // If the login URL is the default one, then it is assumed not to have been set explicitly
+        if (DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL == formLoginPage) {
+        	formLoginPage = null;
+        }
+        String openIDLoginPage = getLoginFormUrl(openID.entryPoint);
+
+        // If no login page has been defined, add in the default page generator.
+        if (needLoginPage && formLoginPage == null && openIDLoginPage == null) {
+            logger.info("No login page configured. The default internal one will be used. Use the '"
+                     + FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page.");
+            BeanDefinitionBuilder loginPageFilter =
+                BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
+
+            if (form.filter != null) {
+                loginPageFilter.addConstructorArgValue(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
+            }
+
+            if (openID.filter != null) {
+                loginPageFilter.addConstructorArgValue(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
+            }
+
+            return loginPageFilter.getBeanDefinition();
+        }
+        return null;
+    }
+
     static UrlMatcher createUrlMatcher(Element element) {
         String patternType = element.getAttribute(ATT_PATH_TYPE);
         if (!StringUtils.hasText(patternType)) {
@@ -625,7 +715,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
      * map used to create the FilterInvocationDefintionSource for the FilterSecurityInterceptor.
      */
     @SuppressWarnings("unchecked")
-    void parseInterceptUrlsForChannelSecurityAndFilterChain(List<Element> urlElts, Map filterChainMap,  Map channelRequestMap,
+    void parseInterceptUrlsForChannelSecurityAndEmptyFilterChains(List<Element> urlElts, Map filterChainMap,  Map channelRequestMap,
             boolean useLowerCasePaths, ParserContext parserContext) {
 
         ConfigAttributeEditor editor = new ConfigAttributeEditor();

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

@@ -79,9 +79,6 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser {
 
         builder.addConstructorArgValue(handlers);
 
-        parserContext.getRegistry().registerBeanDefinition(BeanIds.LOGOUT_FILTER, builder.getBeanDefinition());
-        ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.LOGOUT_FILTER));
-
-        return null;
+        return builder.getBeanDefinition();
     }
 }

+ 3 - 6
config/src/main/java/org/springframework/security/config/RememberMeBeanDefinitionParser.java

@@ -116,9 +116,7 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
 
         registerProvider(parserContext, source, key);
 
-        registerFilter(parserContext, source);
-
-        return null;
+        return createFilter(parserContext, source);
     }
 
     String getServicesName() {
@@ -134,7 +132,7 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
         ConfigUtils.addAuthenticationProvider(pc, BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER);
     }
 
-    private void registerFilter(ParserContext pc, Object source) {
+    private BeanDefinition createFilter(ParserContext pc, Object source) {
         RootBeanDefinition filter = new RootBeanDefinition(RememberMeProcessingFilter.class);
         filter.setSource(source);
         filter.getPropertyValues().addPropertyValue("authenticationManager",
@@ -143,7 +141,6 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
         filter.getPropertyValues().addPropertyValue("rememberMeServices",
                 new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES));
 
-        pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_FILTER, filter);
-        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.REMEMBER_ME_FILTER));
+        return filter;
     }
 }

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

@@ -61,9 +61,6 @@ public class X509BeanDefinitionParser implements BeanDefinitionParser {
 
         filterBuilder.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
 
-        parserContext.getRegistry().registerBeanDefinition(BeanIds.X509_FILTER, filterBuilder.getBeanDefinition());
-        ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.X509_FILTER));
-
-        return null;
+        return filterBuilder.getBeanDefinition();
     }
 }