SEC-792: Filters should only be added to the default stack if they are labelled using custom-filter.

http://jira.springframework.org/browse/SEC-792. The filters are now maintained as a list in the context and have to be stored there explicitly on registration.
This commit is contained in:
Luke Taylor 2008-04-23 16:06:54 +00:00
parent 80cd7f4acc
commit 38774ec94f
12 changed files with 134 additions and 106 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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";

View File

@ -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);

View File

@ -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;
}
}
}

View File

@ -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 <custom-filter>
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;
}
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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 <tt>Ordered</tt>
* 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;
}
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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(
"<http auto-config='true'/>" + AUTH_PROVIDER_XML +
"<b:bean id='userFilter' class='org.springframework.security.util.MockFilter'>" +
@ -268,7 +269,9 @@ public class HttpSecurityBeanDefinitionParserTests {
"<b:bean id='userFilter2' class='org.springframework.security.util.MockFilter'>" +
" <custom-filter position='FIRST'/>" +
"</b:bean>" +
"<b:bean id='userFilter3' class='org.springframework.security.util.MockFilter'/>");
"<b:bean id='userFilter3' class='org.springframework.security.util.MockFilter'/>" +
"<b:bean id='userFilter4' class='org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter'/>"
);
List filters = getFilters("/someurl");
assertEquals(13, filters.size());