diff --git a/core/src/main/java/org/springframework/security/config/AnonymousBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/AnonymousBeanDefinitionParser.java index 5d5a78b5e9..e5fb22e6c1 100644 --- a/core/src/main/java/org/springframework/security/config/AnonymousBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/AnonymousBeanDefinitionParser.java @@ -3,6 +3,7 @@ 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.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; @@ -70,6 +71,7 @@ public class AnonymousBeanDefinitionParser implements BeanDefinitionParser { authMgrProviderList.add(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; diff --git a/core/src/main/java/org/springframework/security/config/BasicAuthenticationBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/BasicAuthenticationBeanDefinitionParser.java index 4142361ae4..2d7470ff2d 100644 --- a/core/src/main/java/org/springframework/security/config/BasicAuthenticationBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/BasicAuthenticationBeanDefinitionParser.java @@ -41,6 +41,7 @@ public class BasicAuthenticationBeanDefinitionParser implements BeanDefinitionPa 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; diff --git a/core/src/main/java/org/springframework/security/config/BeanIds.java b/core/src/main/java/org/springframework/security/config/BeanIds.java index c0093163d3..295f3225f4 100644 --- a/core/src/main/java/org/springframework/security/config/BeanIds.java +++ b/core/src/main/java/org/springframework/security/config/BeanIds.java @@ -18,6 +18,7 @@ public abstract class BeanIds { static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor"; static final String HTTP_POST_PROCESSOR = "_httpConfigBeanFactoryPostProcessor"; 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"; diff --git a/core/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java index b2d85e30c1..28a11ec12c 100644 --- a/core/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java @@ -83,6 +83,7 @@ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionPar 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)); BeanDefinition providerManager = ConfigUtils.registerProviderManagerIfNecessary(parserContext); diff --git a/core/src/main/java/org/springframework/security/config/ConfigUtils.java b/core/src/main/java/org/springframework/security/config/ConfigUtils.java index 862a893762..491c036d7d 100644 --- a/core/src/main/java/org/springframework/security/config/ConfigUtils.java +++ b/core/src/main/java/org/springframework/security/config/ConfigUtils.java @@ -1,7 +1,11 @@ package org.springframework.security.config; +import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.BeanMetadataElement; +import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.RuntimeBeanReference; @@ -83,7 +87,6 @@ public abstract class ConfigUtils { return authManager; } - /** * Obtains a user details service for use in RememberMeServices etc. Will return a caching version * if available so should not be used for beans which need to separate the two. @@ -110,4 +113,50 @@ public abstract class ConfigUtils { BeanDefinition authManager = registerProviderManagerIfNecessary(parserContext); return (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue(); } + + private static void registerFilterChainPostProcessorIfNecessary(ParserContext pc) { + if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_POST_PROCESSOR)) { + return; + } + // Post processor specifically to assemble and order the filter chain immediately before the FilterChainProxy is initialized. + RootBeanDefinition filterChainPostProcessor = new RootBeanDefinition(FilterChainProxyPostProcessor.class); + filterChainPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_POST_PROCESSOR, filterChainPostProcessor); + RootBeanDefinition filterList = new RootBeanDefinition(FilterChainList.class); + filterList.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_LIST, filterList); + } + + static void addHttpFilter(ParserContext pc, BeanMetadataElement filter) { + registerFilterChainPostProcessorIfNecessary(pc); + + RootBeanDefinition filterList = (RootBeanDefinition) pc.getRegistry().getBeanDefinition(BeanIds.FILTER_LIST); + + ManagedList filters; + MutablePropertyValues pvs = filterList.getPropertyValues(); + if (pvs.contains("filters")) { + filters = (ManagedList) pvs.getPropertyValue("filters").getValue(); + } else { + filters = new ManagedList(); + pvs.addPropertyValue("filters", filters); + } + + filters.add(filter); + } + + /** + * Bean which holds the list of filters which are maintained in the context and modified by calls to + * addHttpFilter. The post processor retrieves these before injecting the list into the FilterChainProxy. + */ + public static class FilterChainList { + List filters; + + public List getFilters() { + return filters; + } + + public void setFilters(List filters) { + this.filters = filters; + } + } } diff --git a/core/src/main/java/org/springframework/security/config/FilterChainProxyPostProcessor.java b/core/src/main/java/org/springframework/security/config/FilterChainProxyPostProcessor.java index 641a1be157..822584a9cf 100644 --- a/core/src/main/java/org/springframework/security/config/FilterChainProxyPostProcessor.java +++ b/core/src/main/java/org/springframework/security/config/FilterChainProxyPostProcessor.java @@ -2,12 +2,9 @@ package org.springframework.security.config; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; -import javax.servlet.Filter; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; @@ -16,9 +13,8 @@ import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.OrderComparator; -import org.springframework.core.Ordered; +import org.springframework.security.config.ConfigUtils.FilterChainList; import org.springframework.security.util.FilterChainProxy; -import org.springframework.util.Assert; /** * @@ -29,70 +25,33 @@ import org.springframework.util.Assert; public class FilterChainProxyPostProcessor implements BeanPostProcessor, BeanFactoryAware { private Log logger = LogFactory.getLog(getClass()); - private ListableBeanFactory beanFactory; - + private ListableBeanFactory beanFactory; + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(!beanName.equals(BeanIds.FILTER_CHAIN_PROXY)) { return bean; } FilterChainProxy filterChainProxy = (FilterChainProxy) bean; - // Set the default match - List defaultFilterChain = orderFilters(beanFactory); - + FilterChainList filterList = (FilterChainList) beanFactory.getBean(BeanIds.FILTER_LIST); + + List filters = new ArrayList(filterList.getFilters()); + Collections.sort(filters, new OrderComparator()); // Note that this returns a copy Map filterMap = filterChainProxy.getFilterChainMap(); - String allUrlsMatch = filterChainProxy.getMatcher().getUniversalMatchPattern(); - - filterMap.put(allUrlsMatch, defaultFilterChain); + filterMap.put(filterChainProxy.getMatcher().getUniversalMatchPattern(), filters); filterChainProxy.setFilterChainMap(filterMap); - logger.info("Configured filter chain(s): " + filterChainProxy); + logger.info("FilterChainProxy: " + filterChainProxy); return bean; } - private List orderFilters(ListableBeanFactory beanFactory) { - Map filters = beanFactory.getBeansOfType(Filter.class); - - Assert.notEmpty(filters, "No filters found in app context!"); - - Iterator ids = filters.keySet().iterator(); - - List orderedFilters = new ArrayList(); - - while (ids.hasNext()) { - String id = (String) ids.next(); - Filter filter = (Filter) filters.get(id); - - if (filter instanceof FilterChainProxy) { - continue; - } - - // Filters must be Spring security filters or wrapped using - if (!filter.getClass().getName().startsWith("org.springframework.security")) { - continue; - } - - if (!(filter instanceof Ordered)) { - logger.info("Filter " + id + " doesn't implement the Ordered interface, skipping it."); - continue; - } - - orderedFilters.add(filter); - } - - Collections.sort(orderedFilters, new OrderComparator()); - - return orderedFilters; - } - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ListableBeanFactory) beanFactory; - } - + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ListableBeanFactory) beanFactory; + } } diff --git a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java index 16b0074181..bc707a49c8 100644 --- a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java @@ -97,7 +97,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_ENTRY_POINT_REF = "entry-point-ref"; static final String ATT_ONCE_PER_REQUEST = "once-per-request"; static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page"; - public BeanDefinition parse(Element element, ParserContext parserContext) { ConfigUtils.registerProviderManagerIfNecessary(parserContext); @@ -117,9 +116,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap, convertPathsToLowerCase, parserContext); - registerHttpSessionIntegrationFilter(element, registry); + registerHttpSessionIntegrationFilter(element, parserContext); - registerServletApiFilter(element, registry); + registerServletApiFilter(element, parserContext); // Set up the access manager reference for http String accessManagerId = element.getAttribute(ATT_ACCESS_MGR); @@ -134,15 +133,15 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), parserContext); registry.registerBeanDefinition(BeanIds.PORT_MAPPER, portMapper); - registerExceptionTranslationFilter(element.getAttribute(ATT_ACCESS_DENIED_PAGE), registry); + registerExceptionTranslationFilter(element.getAttribute(ATT_ACCESS_DENIED_PAGE), parserContext); if (channelRequestMap.size() > 0) { // At least one channel requirement has been specified - registerChannelProcessingBeans(parserContext.getRegistry(), matcher, channelRequestMap); + registerChannelProcessingBeans(parserContext, matcher, channelRequestMap); } - registerFilterSecurityInterceptor(element, registry, matcher, accessManagerId, + registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId, parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, parserContext)); boolean sessionControlEnabled = registerConcurrentSessionControlBeansIfRequired(element, parserContext); @@ -200,15 +199,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher); filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap); pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy); - pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN); - - // Post processor specifically to assemble and order the filter chain immediately before the FilterChainProxy is initialized. - RootBeanDefinition filterChainPostProcessor = new RootBeanDefinition(FilterChainProxyPostProcessor.class); - filterChainPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_POST_PROCESSOR, filterChainPostProcessor); + pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN); } - private void registerHttpSessionIntegrationFilter(Element element, BeanDefinitionRegistry registry) { + private void registerHttpSessionIntegrationFilter(Element element, ParserContext pc) { RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class); String createSession = element.getAttribute(ATT_CREATE_SESSION); @@ -224,19 +218,21 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.FALSE); } - registry.registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif); + pc.getRegistry().registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif); + ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER)); } // Adds the servlet-api integration filter if required - private void registerServletApiFilter(Element element, BeanDefinitionRegistry registry) { + private void registerServletApiFilter(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)) { - registry.registerBeanDefinition(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER, + 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)); } } @@ -253,7 +249,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { return true; } - private void registerExceptionTranslationFilter(String accessDeniedPage, BeanDefinitionRegistry registry) { + private void registerExceptionTranslationFilter(String accessDeniedPage, ParserContext pc) { BeanDefinitionBuilder exceptionTranslationFilterBuilder = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class); @@ -263,10 +259,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { exceptionTranslationFilterBuilder.addPropertyValue("accessDeniedHandler", accessDeniedHandler); } - registry.registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition()); + pc.getRegistry().registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition()); + ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.EXCEPTION_TRANSLATION_FILTER)); } - private void registerFilterSecurityInterceptor(Element element, BeanDefinitionRegistry registry, UrlMatcher matcher, + private void registerFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher, String accessManagerId, LinkedHashMap filterInvocationDefinitionMap) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class); @@ -279,10 +276,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { builder.addPropertyValue("objectDefinitionSource", new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap)); - registry.registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition()); + pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition()); + ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR)); } - private void registerChannelProcessingBeans(BeanDefinitionRegistry registry, UrlMatcher matcher, LinkedHashMap channelRequestMap) { + private void registerChannelProcessingBeans(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) { RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class); channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager", new RuntimeBeanReference(BeanIds.CHANNEL_DECISION_MANAGER)); @@ -307,11 +305,13 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { channelProcessors.add(inSecureChannelProcessor); channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", channelProcessors); - registry.registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter); - registry.registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager); + 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); + } - private void registerSessionFixationProtectionFilter(ParserContext parserContext, String sessionFixationAttribute, boolean sessionControlEnabled) { + private void registerSessionFixationProtectionFilter(ParserContext pc, String sessionFixationAttribute, boolean sessionControlEnabled) { if(!StringUtils.hasText(sessionFixationAttribute)) { sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION; } @@ -324,13 +324,14 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { if (sessionControlEnabled) { sessionFixationFilter.addPropertyReference("sessionRegistry", BeanIds.SESSION_REGISTRY); } - parserContext.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER, + pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER, sessionFixationFilter.getBeanDefinition()); + ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER)); } } - private void parseBasicFormLoginAndOpenID(Element element, ParserContext parserContext, boolean autoConfig) { + private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig) { RootBeanDefinition formLoginFilter = null; RootBeanDefinition formLoginEntryPoint = null; String formLoginPage = null; @@ -345,7 +346,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH); if (basicAuthElt != null || autoConfig) { - new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, parserContext); + new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc); } Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN); @@ -354,7 +355,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check", "org.springframework.security.ui.webapp.AuthenticationProcessingFilter"); - parser.parse(formLoginElt, parserContext); + parser.parse(formLoginElt, pc); formLoginFilter = parser.getFilterBean(); formLoginEntryPoint = parser.getEntryPointBean(); formLoginPage = parser.getLoginPage(); @@ -366,7 +367,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check", "org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter"); - parser.parse(openIDLoginElt, parserContext); + parser.parse(openIDLoginElt, pc); openIDFilter = parser.getFilterBean(); openIDEntryPoint = parser.getEntryPointBean(); openIDLoginPage = parser.getLoginPage(); @@ -381,23 +382,25 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { } BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition(); - ConfigUtils.getRegisteredProviders(parserContext).add(openIDProvider); + ConfigUtils.getRegisteredProviders(pc).add(openIDProvider); - parserContext.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider); + pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider); } boolean needLoginPage = false; if (formLoginFilter != null) { needLoginPage = true; - parserContext.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter); - parserContext.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint); + 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; - parserContext.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter); - parserContext.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint); + 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. @@ -415,8 +418,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER)); } - parserContext.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER, + pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER, loginPageFilter.getBeanDefinition()); + ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER)); } // We need to establish the main entry point. @@ -424,39 +428,39 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { String customEntryPoint = element.getAttribute(ATT_ENTRY_POINT_REF); if (StringUtils.hasText(customEntryPoint)) { - parserContext.getRegistry().registerAlias(customEntryPoint, BeanIds.MAIN_ENTRY_POINT); + pc.getRegistry().registerAlias(customEntryPoint, BeanIds.MAIN_ENTRY_POINT); return; } // Basic takes precedence if explicit element is used and no others are configured if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null) { - parserContext.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); + pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); return; } // 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) { - parserContext.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); + pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); return; } // Otherwise use OpenID if enabled if (openIDFilter != null && formLoginFilter == null) { - parserContext.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); + pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); return; } // If X.509 has been enabled, use the preauth entry point. if (DomUtils.getChildElementByTagName(element, Elements.X509) != null) { - parserContext.getRegistry().registerAlias(BeanIds.PRE_AUTH_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); + pc.getRegistry().registerAlias(BeanIds.PRE_AUTH_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); return; } - parserContext.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " + + 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 ", - parserContext.extractSource(element)); + pc.extractSource(element)); } static UrlMatcher createUrlMatcher(Element element) { diff --git a/core/src/main/java/org/springframework/security/config/LogoutBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/LogoutBeanDefinitionParser.java index f5d9642db1..19b1ab990f 100644 --- a/core/src/main/java/org/springframework/security/config/LogoutBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/LogoutBeanDefinitionParser.java @@ -70,7 +70,8 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser { builder.addConstructorArg(handlers); parserContext.getRegistry().registerBeanDefinition(BeanIds.LOGOUT_FILTER, builder.getBeanDefinition()); - + ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.LOGOUT_FILTER)); + return null; } } diff --git a/core/src/main/java/org/springframework/security/config/OrderedFilterBeanDefinitionDecorator.java b/core/src/main/java/org/springframework/security/config/OrderedFilterBeanDefinitionDecorator.java index abba887051..0b29a4524f 100644 --- a/core/src/main/java/org/springframework/security/config/OrderedFilterBeanDefinitionDecorator.java +++ b/core/src/main/java/org/springframework/security/config/OrderedFilterBeanDefinitionDecorator.java @@ -9,8 +9,8 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; -import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.BeanDefinitionDecorator; import org.springframework.beans.factory.xml.ParserContext; @@ -22,8 +22,8 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; /** - * Replaces a Spring bean of type "Filter" with a wrapper class which implements the Ordered - * interface. This allows user to add their own filter to the security chain. If the user's filter + * Adds the decorated "Filter" bean into the standard filter chain maintained by the FilterChainProxy. + * This allows user to add their own custom filters to the security chain. If the user's filter * already implements Ordered, and no "order" attribute is specified, the filter's default order will be used. * * @author Luke Taylor @@ -39,16 +39,17 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor Element elt = (Element)node; String order = getOrder(elt, parserContext); - BeanDefinition filter = holder.getBeanDefinition(); BeanDefinitionBuilder wrapper = BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.config.OrderedFilterBeanDefinitionDecorator$OrderedFilterDecorator"); wrapper.addConstructorArg(holder.getBeanName()); - wrapper.addConstructorArg(filter); + wrapper.addConstructorArg(new RuntimeBeanReference(holder.getBeanName())); if (StringUtils.hasText(order)) { wrapper.addPropertyValue("order", order); } - return new BeanDefinitionHolder(wrapper.getBeanDefinition(), holder.getBeanName()); + ConfigUtils.addHttpFilter(parserContext, wrapper.getBeanDefinition()); + + return holder; } /** @@ -123,5 +124,9 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor public String toString() { return "OrderedFilterDecorator[ delegate=" + delegate + "; order=" + getOrder() + "]"; } + + Filter getDelegate() { + return delegate; + } } } diff --git a/core/src/main/java/org/springframework/security/config/RememberMeBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/RememberMeBeanDefinitionParser.java index d38ee03405..624c6b2286 100644 --- a/core/src/main/java/org/springframework/security/config/RememberMeBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/RememberMeBeanDefinitionParser.java @@ -103,6 +103,7 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser { parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services); parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_FILTER, filter); + ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.REMEMBER_ME_FILTER)); return null; } diff --git a/core/src/main/java/org/springframework/security/config/X509BeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/X509BeanDefinitionParser.java index fe261608f8..53b65cfe1e 100644 --- a/core/src/main/java/org/springframework/security/config/X509BeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/X509BeanDefinitionParser.java @@ -62,6 +62,7 @@ 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; } diff --git a/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java b/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java index 278b383a81..c30192b83b 100644 --- a/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java +++ b/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java @@ -259,7 +259,8 @@ public class HttpSecurityBeanDefinitionParserTests { @Test public void externalFiltersAreTreatedCorrectly() throws Exception { - // Decorated user-filter should be added to stack. The other one should be ignored + // Decorated user-filter should be added to stack. The other MockFilter and the un-decorated standard filter + // should be ignored setContext( "" + AUTH_PROVIDER_XML + "" + @@ -268,7 +269,9 @@ public class HttpSecurityBeanDefinitionParserTests { "" + " " + "" + - ""); + "" + + "" + ); List filters = getFilters("/someurl"); assertEquals(13, filters.size());