mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-30 16:52:13 +00:00
SEC-1657: Corresponding namespace updates to use SecurityFilterChain list in place of filterChainMap.
This commit is contained in:
parent
37d0454fd7
commit
04dc65c8fe
@ -25,6 +25,7 @@ public abstract class BeanIds {
|
|||||||
public static final String METHOD_ACCESS_MANAGER = PREFIX + "defaultMethodAccessManager";
|
public static final String METHOD_ACCESS_MANAGER = PREFIX + "defaultMethodAccessManager";
|
||||||
|
|
||||||
public static final String FILTER_CHAIN_PROXY = PREFIX + "filterChainProxy";
|
public static final String FILTER_CHAIN_PROXY = PREFIX + "filterChainProxy";
|
||||||
|
public static final String FILTER_CHAINS = PREFIX + "filterChains";
|
||||||
|
|
||||||
public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = PREFIX + "methodSecurityMetadataSourceAdvisor";
|
public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = PREFIX + "methodSecurityMetadataSourceAdvisor";
|
||||||
public static final String EMBEDDED_APACHE_DS = PREFIX + "apacheDirectoryServerContainer";
|
public static final String EMBEDDED_APACHE_DS = PREFIX + "apacheDirectoryServerContainer";
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package org.springframework.security.config;
|
package org.springframework.security.config;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
@ -15,6 +12,7 @@ import org.springframework.security.config.authentication.AuthenticationManagerB
|
|||||||
import org.springframework.security.config.authentication.AuthenticationProviderBeanDefinitionParser;
|
import org.springframework.security.config.authentication.AuthenticationProviderBeanDefinitionParser;
|
||||||
import org.springframework.security.config.authentication.JdbcUserServiceBeanDefinitionParser;
|
import org.springframework.security.config.authentication.JdbcUserServiceBeanDefinitionParser;
|
||||||
import org.springframework.security.config.authentication.UserServiceBeanDefinitionParser;
|
import org.springframework.security.config.authentication.UserServiceBeanDefinitionParser;
|
||||||
|
import org.springframework.security.config.http.FilterChainBeanDefinitionParser;
|
||||||
import org.springframework.security.config.http.FilterChainMapBeanDefinitionDecorator;
|
import org.springframework.security.config.http.FilterChainMapBeanDefinitionDecorator;
|
||||||
import org.springframework.security.config.http.FilterInvocationSecurityMetadataSourceParser;
|
import org.springframework.security.config.http.FilterInvocationSecurityMetadataSourceParser;
|
||||||
import org.springframework.security.config.http.HttpFirewallBeanDefinitionParser;
|
import org.springframework.security.config.http.HttpFirewallBeanDefinitionParser;
|
||||||
@ -30,6 +28,8 @@ import org.springframework.util.ClassUtils;
|
|||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses elements from the "security" namespace (http://www.springframework.org/schema/security).
|
* Parses elements from the "security" namespace (http://www.springframework.org/schema/security).
|
||||||
*
|
*
|
||||||
@ -76,7 +76,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
|
|
||||||
if (parser == null) {
|
if (parser == null) {
|
||||||
if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) ||
|
if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) ||
|
||||||
Elements.FILTER_CHAIN_MAP.equals(name)) {
|
Elements.FILTER_CHAIN_MAP.equals(name) || Elements.FILTER_CHAIN.equals(name)) {
|
||||||
reportMissingWebClasses(name, pc, element);
|
reportMissingWebClasses(name, pc, element);
|
||||||
} else {
|
} else {
|
||||||
reportUnsupportedNodeType(name, pc, element);
|
reportUnsupportedNodeType(name, pc, element);
|
||||||
@ -147,6 +147,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser());
|
parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser());
|
||||||
parsers.put(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
parsers.put(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||||
parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||||
|
parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser());
|
||||||
filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
|
filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package org.springframework.security.config.debug;
|
package org.springframework.security.config.debug;
|
||||||
|
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
import org.springframework.security.web.util.RequestMatcher;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.util.UrlUtils;
|
import org.springframework.security.web.util.UrlUtils;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
@ -13,8 +13,7 @@ import javax.servlet.http.HttpServletRequestWrapper;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spring Security debugging filter.
|
* Spring Security debugging filter.
|
||||||
@ -28,12 +27,10 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
class DebugFilter extends OncePerRequestFilter {
|
class DebugFilter extends OncePerRequestFilter {
|
||||||
private final FilterChainProxy fcp;
|
private final FilterChainProxy fcp;
|
||||||
private final Map<RequestMatcher, List<Filter>> filterChainMap;
|
|
||||||
private final Logger logger = new Logger();
|
private final Logger logger = new Logger();
|
||||||
|
|
||||||
public DebugFilter(FilterChainProxy fcp) {
|
public DebugFilter(FilterChainProxy fcp) {
|
||||||
this.fcp = fcp;
|
this.fcp = fcp;
|
||||||
this.filterChainMap = fcp.getFilterChainMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -67,11 +64,9 @@ class DebugFilter extends OncePerRequestFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<Filter> getFilters(HttpServletRequest request) {
|
private List<Filter> getFilters(HttpServletRequest request) {
|
||||||
for (Map.Entry<RequestMatcher, List<Filter>> entry : filterChainMap.entrySet()) {
|
for (SecurityFilterChain chain : fcp.getFilterChains()) {
|
||||||
RequestMatcher matcher = entry.getKey();
|
if (chain.matches(request)) {
|
||||||
|
return chain.getFilters();
|
||||||
if (matcher.matches(request)) {
|
|
||||||
return entry.getValue();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.springframework.security.config.http;
|
package org.springframework.security.config.http;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
|
|
||||||
@ -12,6 +11,7 @@ import org.springframework.security.access.ConfigAttribute;
|
|||||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
import org.springframework.security.web.FilterInvocation;
|
import org.springframework.security.web.FilterInvocation;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||||
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
|
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
|
||||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||||
@ -29,9 +29,23 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||||||
private final Log logger = LogFactory.getLog(getClass());
|
private final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
public void validate(FilterChainProxy fcp) {
|
public void validate(FilterChainProxy fcp) {
|
||||||
for(List<Filter> filters : fcp.getFilterChainMap().values()) {
|
for(SecurityFilterChain filterChain : fcp.getFilterChains()) {
|
||||||
checkLoginPageIsntProtected(fcp, filters);
|
checkLoginPageIsntProtected(fcp, filterChain.getFilters());
|
||||||
checkFilterStack(filters);
|
checkFilterStack(filterChain.getFilters());
|
||||||
|
}
|
||||||
|
|
||||||
|
checkForDuplicateMatchers(new ArrayList<SecurityFilterChain>(fcp.getFilterChains()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkForDuplicateMatchers(List<SecurityFilterChain> chains) {
|
||||||
|
SecurityFilterChain chain = chains.remove(0);
|
||||||
|
|
||||||
|
for (SecurityFilterChain test : chains) {
|
||||||
|
if (chain.getRequestMatcher().equals(test.getRequestMatcher())) {
|
||||||
|
throw new IllegalArgumentException("The FilterChainProxy contains two filter chains using the" +
|
||||||
|
" matcher " + chain.getRequestMatcher() + ". If you are using multiple <http> namespace " +
|
||||||
|
"elements, you must use a 'pattern' attribute to define the request patterns to which they apply.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package org.springframework.security.config.http;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.ManagedList;
|
||||||
|
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luke Taylor
|
||||||
|
*/
|
||||||
|
public class FilterChainBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class getBeanClass(Element element) {
|
||||||
|
return SecurityFilterChain.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doParse(Element elt, BeanDefinitionBuilder builder) {
|
||||||
|
MatcherType matcherType = MatcherType.fromElement(elt);
|
||||||
|
String path = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN);
|
||||||
|
String filters = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS);
|
||||||
|
|
||||||
|
builder.addConstructorArgValue(matcherType.createMatcher(path, null));
|
||||||
|
|
||||||
|
if (filters.equals(HttpSecurityBeanDefinitionParser.OPT_FILTERS_NONE)) {
|
||||||
|
builder.addConstructorArgValue(Collections.EMPTY_LIST);
|
||||||
|
} else {
|
||||||
|
String[] filterBeanNames = StringUtils.tokenizeToStringArray(filters, ",");
|
||||||
|
ManagedList<RuntimeBeanReference> filterChain = new ManagedList<RuntimeBeanReference>(filterBeanNames.length);
|
||||||
|
|
||||||
|
for (String name : filterBeanNames) {
|
||||||
|
filterChain.add(new RuntimeBeanReference(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.addConstructorArgValue(filterChain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -95,13 +95,13 @@ class HttpConfigurationBuilder {
|
|||||||
private BeanReference fsi;
|
private BeanReference fsi;
|
||||||
private BeanReference requestCache;
|
private BeanReference requestCache;
|
||||||
|
|
||||||
public HttpConfigurationBuilder(Element element, ParserContext pc, MatcherType matcherType,
|
public HttpConfigurationBuilder(Element element, ParserContext pc,
|
||||||
String portMapperName, BeanReference authenticationManager) {
|
String portMapperName, BeanReference authenticationManager) {
|
||||||
|
|
||||||
this.httpElt = element;
|
this.httpElt = element;
|
||||||
this.pc = pc;
|
this.pc = pc;
|
||||||
this.portMapperName = portMapperName;
|
this.portMapperName = portMapperName;
|
||||||
this.matcherType = matcherType;
|
this.matcherType = MatcherType.fromElement(element);
|
||||||
interceptUrls = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
|
interceptUrls = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
|
||||||
|
|
||||||
for (Element urlElt : interceptUrls) {
|
for (Element urlElt : interceptUrls) {
|
||||||
@ -339,7 +339,7 @@ class HttpConfigurationBuilder {
|
|||||||
servApiFilter = new RootBeanDefinition(SecurityContextHolderAwareRequestFilter.class);
|
servApiFilter = new RootBeanDefinition(SecurityContextHolderAwareRequestFilter.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds the jaas-api integration filter if required
|
// Adds the jaas-api integration filter if required
|
||||||
private void createJaasApiFilter() {
|
private void createJaasApiFilter() {
|
||||||
final String ATT_JAAS_API_PROVISION = "jaas-api-provision";
|
final String ATT_JAAS_API_PROVISION = "jaas-api-provision";
|
||||||
@ -354,7 +354,7 @@ class HttpConfigurationBuilder {
|
|||||||
jaasApiFilter = new RootBeanDefinition(JaasApiIntegrationFilter.class);
|
jaasApiFilter = new RootBeanDefinition(JaasApiIntegrationFilter.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createChannelProcessingFilter() {
|
private void createChannelProcessingFilter() {
|
||||||
ManagedMap<BeanDefinition,BeanDefinition> channelRequestMap = parseInterceptUrlsForChannelSecurity();
|
ManagedMap<BeanDefinition,BeanDefinition> channelRequestMap = parseInterceptUrlsForChannelSecurity();
|
||||||
|
|
||||||
@ -534,7 +534,7 @@ class HttpConfigurationBuilder {
|
|||||||
if (jaasApiFilter != null) {
|
if (jaasApiFilter != null) {
|
||||||
filters.add(new OrderDecorator(jaasApiFilter, JAAS_API_SUPPORT_FILTER));
|
filters.add(new OrderDecorator(jaasApiFilter, JAAS_API_SUPPORT_FILTER));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sfpf != null) {
|
if (sfpf != null) {
|
||||||
filters.add(new OrderDecorator(sfpf, SESSION_MANAGEMENT_FILTER));
|
filters.add(new OrderDecorator(sfpf, SESSION_MANAGEMENT_FILTER));
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,13 @@
|
|||||||
package org.springframework.security.config.http;
|
package org.springframework.security.config.http;
|
||||||
|
|
||||||
import org.springframework.beans.BeanMetadataElement;
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.BeanReference;
|
|
||||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
import org.springframework.beans.factory.support.ManagedMap;
|
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.security.config.BeanIds;
|
import org.springframework.security.config.BeanIds;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injects the supplied {@code HttpFirewall} bean reference into the {@code FilterChainProxy}.
|
* Injects the supplied {@code HttpFirewall} bean reference into the {@code FilterChainProxy}.
|
||||||
*
|
*
|
||||||
@ -28,9 +23,7 @@ public class HttpFirewallBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the FCP is registered.
|
// Ensure the FCP is registered.
|
||||||
HttpSecurityBeanDefinitionParser.registerFilterChainProxy(pc,
|
HttpSecurityBeanDefinitionParser.registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));
|
||||||
new ManagedMap<BeanDefinition, BeanReference>(),
|
|
||||||
pc.extractSource(element));
|
|
||||||
BeanDefinition filterChainProxy = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAIN_PROXY);
|
BeanDefinition filterChainProxy = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAIN_PROXY);
|
||||||
filterChainProxy.getPropertyValues().addPropertyValue("firewall", new RuntimeBeanReference(ref));
|
filterChainProxy.getPropertyValues().addPropertyValue("firewall", new RuntimeBeanReference(ref));
|
||||||
|
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
package org.springframework.security.config.http;
|
package org.springframework.security.config.http;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.beans.BeanMetadataElement;
|
import org.springframework.beans.BeanMetadataElement;
|
||||||
@ -13,12 +8,10 @@ import org.springframework.beans.factory.config.BeanReference;
|
|||||||
import org.springframework.beans.factory.config.ListFactoryBean;
|
import org.springframework.beans.factory.config.ListFactoryBean;
|
||||||
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
|
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
|
||||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
|
||||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.ManagedList;
|
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.support.RootBeanDefinition;
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
@ -29,11 +22,14 @@ import org.springframework.security.config.BeanIds;
|
|||||||
import org.springframework.security.config.Elements;
|
import org.springframework.security.config.Elements;
|
||||||
import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
|
import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.util.AnyRequestMatcher;
|
import org.springframework.security.web.util.AnyRequestMatcher;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.util.xml.DomUtils;
|
import org.springframework.util.xml.DomUtils;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up HTTP security: filter stack and protected URLs.
|
* Sets up HTTP security: filter stack and protected URLs.
|
||||||
*
|
*
|
||||||
@ -67,33 +63,29 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
* By the end of this method, the default <tt>FilterChainProxy</tt> bean should have been registered and will have
|
* By the end of this method, the default <tt>FilterChainProxy</tt> bean should have been registered and will have
|
||||||
* the map of filter chains defined, with the "universal" match pattern mapped to the list of beans which have been parsed here.
|
* the map of filter chains defined, with the "universal" match pattern mapped to the list of beans which have been parsed here.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||||
CompositeComponentDefinition compositeDef =
|
CompositeComponentDefinition compositeDef =
|
||||||
new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
|
new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
|
||||||
pc.pushContainingComponent(compositeDef);
|
pc.pushContainingComponent(compositeDef);
|
||||||
|
|
||||||
MatcherType matcherType = MatcherType.fromElement(element);
|
registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));
|
||||||
ManagedMap<BeanDefinition, BeanReference> filterChainMap = new ManagedMap<BeanDefinition, BeanReference>();
|
|
||||||
|
|
||||||
String filterChainPattern = element.getAttribute(ATT_PATH_PATTERN);
|
// Obtain the filter chains and add the new chain to it
|
||||||
|
BeanDefinition listFactoryBean = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAINS);
|
||||||
|
List<BeanReference> filterChains = (List<BeanReference>)
|
||||||
|
listFactoryBean.getPropertyValues().getPropertyValue("sourceList").getValue();
|
||||||
|
|
||||||
BeanDefinition filterChainMatcher;
|
filterChains.add(createFilterChain(element, pc));
|
||||||
|
|
||||||
if (StringUtils.hasText(filterChainPattern)) {
|
|
||||||
filterChainMatcher = matcherType.createMatcher(filterChainPattern, null);
|
|
||||||
} else {
|
|
||||||
filterChainMatcher = new RootBeanDefinition(AnyRequestMatcher.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
filterChainMap.put(filterChainMatcher, createFilterChain(element, pc, matcherType));
|
|
||||||
|
|
||||||
registerFilterChainProxy(pc, filterChainMap, pc.extractSource(element));
|
|
||||||
|
|
||||||
pc.popAndRegisterContainingComponent();
|
pc.popAndRegisterContainingComponent();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
BeanReference createFilterChain(Element element, ParserContext pc, MatcherType matcherType) {
|
/**
|
||||||
|
* Creates the {@code SecurityFilterChain} bean from an <http> element.
|
||||||
|
*/
|
||||||
|
private BeanReference createFilterChain(Element element, ParserContext pc) {
|
||||||
boolean secured = !OPT_SECURITY_NONE.equals(element.getAttribute(ATT_SECURED));
|
boolean secured = !OPT_SECURITY_NONE.equals(element.getAttribute(ATT_SECURED));
|
||||||
|
|
||||||
if (!secured) {
|
if (!secured) {
|
||||||
@ -109,7 +101,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return createFilterListBean(element, pc, Collections.emptyList());
|
return createSecurityFilterChainBean(element, pc, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
final String portMapperName = createPortMapper(element, pc);
|
final String portMapperName = createPortMapper(element, pc);
|
||||||
@ -117,7 +109,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();
|
ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();
|
||||||
BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders);
|
BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders);
|
||||||
|
|
||||||
HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc, matcherType,
|
HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc,
|
||||||
portMapperName, authenticationManager);
|
portMapperName, authenticationManager);
|
||||||
|
|
||||||
AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, pc,
|
AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, pc,
|
||||||
@ -135,27 +127,41 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
Collections.sort(unorderedFilterChain, new OrderComparator());
|
Collections.sort(unorderedFilterChain, new OrderComparator());
|
||||||
checkFilterChainOrder(unorderedFilterChain, pc, pc.extractSource(element));
|
checkFilterChainOrder(unorderedFilterChain, pc, pc.extractSource(element));
|
||||||
|
|
||||||
|
// The list of filter beans
|
||||||
List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();
|
List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();
|
||||||
|
|
||||||
for (OrderDecorator od : unorderedFilterChain) {
|
for (OrderDecorator od : unorderedFilterChain) {
|
||||||
filterChain.add(od.bean);
|
filterChain.add(od.bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
return createFilterListBean(element, pc, filterChain);
|
return createSecurityFilterChainBean(element, pc, filterChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BeanReference createFilterListBean(Element element, ParserContext pc, List<?> filterChain) {
|
private BeanReference createSecurityFilterChainBean(Element element, ParserContext pc, List<?> filterChain) {
|
||||||
BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class);
|
BeanDefinition filterChainMatcher;
|
||||||
|
|
||||||
|
String filterChainPattern = element.getAttribute(ATT_PATH_PATTERN);
|
||||||
|
if (StringUtils.hasText(filterChainPattern)) {
|
||||||
|
filterChainMatcher = MatcherType.fromElement(element).createMatcher(filterChainPattern, null);
|
||||||
|
} else {
|
||||||
|
filterChainMatcher = new RootBeanDefinition(AnyRequestMatcher.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
BeanDefinitionBuilder filterChainBldr = BeanDefinitionBuilder.rootBeanDefinition(SecurityFilterChain.class);
|
||||||
|
filterChainBldr.addConstructorArgValue(filterChainMatcher);
|
||||||
|
filterChainBldr.addConstructorArgValue(filterChain);
|
||||||
|
|
||||||
|
BeanDefinition filterChainBean = filterChainBldr.getBeanDefinition();
|
||||||
|
|
||||||
String id = element.getAttribute("name");
|
String id = element.getAttribute("name");
|
||||||
if (!StringUtils.hasText(id)) {
|
if (!StringUtils.hasText(id)) {
|
||||||
id = element.getAttribute("id");
|
id = element.getAttribute("id");
|
||||||
if (!StringUtils.hasText(id)) {
|
if (!StringUtils.hasText(id)) {
|
||||||
id = pc.getReaderContext().generateBeanName(listFactoryBean);
|
id = pc.getReaderContext().generateBeanName(filterChainBean);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
listFactoryBean.getPropertyValues().add("sourceList", filterChain);
|
|
||||||
pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, id));
|
pc.registerBeanComponent(new BeanComponentDefinition(filterChainBean, id));
|
||||||
|
|
||||||
return new RuntimeBeanReference(id);
|
return new RuntimeBeanReference(id);
|
||||||
}
|
}
|
||||||
@ -262,35 +268,22 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
return customFilters;
|
return customFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
static void registerFilterChainProxyIfNecessary(ParserContext pc, Object source) {
|
||||||
static void registerFilterChainProxy(ParserContext pc, Map<BeanDefinition, BeanReference> filterChainMap, Object source) {
|
|
||||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
|
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
|
||||||
// Already registered. Obtain the filter chain map and add the new entries to it
|
return;
|
||||||
|
|
||||||
BeanDefinition fcp = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAIN_PROXY);
|
|
||||||
Map existingFilterChainMap = (Map) fcp.getPropertyValues().getPropertyValue("filterChainMap").getValue();
|
|
||||||
|
|
||||||
for (BeanDefinition matcherBean : filterChainMap.keySet()) {
|
|
||||||
if (existingFilterChainMap.containsKey(matcherBean)) {
|
|
||||||
Map<Integer,ValueHolder> args = matcherBean.getConstructorArgumentValues().getIndexedArgumentValues();
|
|
||||||
String matcherError = args.size() == 2 ? args.get(0).getValue() + ", " +args.get(1).getValue() :
|
|
||||||
matcherBean.toString();
|
|
||||||
pc.getReaderContext().error("The filter chain map already contains this request matcher ["
|
|
||||||
+ matcherError + "]. If you are using multiple <http> namespace elements, you must use a 'pattern' attribute" +
|
|
||||||
" to define the request patterns to which they apply.", source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
existingFilterChainMap.putAll(filterChainMap);
|
|
||||||
} else {
|
|
||||||
// Not already registered, so register it
|
|
||||||
BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class);
|
|
||||||
fcpBldr.getRawBeanDefinition().setSource(source);
|
|
||||||
fcpBldr.addPropertyValue("filterChainMap", filterChainMap);
|
|
||||||
fcpBldr.addPropertyValue("filterChainValidator", new RootBeanDefinition(DefaultFilterChainValidator.class));
|
|
||||||
BeanDefinition fcpBean = fcpBldr.getBeanDefinition();
|
|
||||||
pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY));
|
|
||||||
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
|
||||||
}
|
}
|
||||||
|
// Not already registered, so register the list of filter chains and the FilterChainProxy
|
||||||
|
BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class);
|
||||||
|
listFactoryBean.getPropertyValues().add("sourceList", new ManagedList());
|
||||||
|
pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, BeanIds.FILTER_CHAINS));
|
||||||
|
|
||||||
|
BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class);
|
||||||
|
fcpBldr.getRawBeanDefinition().setSource(source);
|
||||||
|
fcpBldr.addConstructorArgReference(BeanIds.FILTER_CHAINS);
|
||||||
|
fcpBldr.addPropertyValue("filterChainValidator", new RootBeanDefinition(DefaultFilterChainValidator.class));
|
||||||
|
BeanDefinition fcpBean = fcpBldr.getBeanDefinition();
|
||||||
|
pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY));
|
||||||
|
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -443,7 +443,7 @@ filter-chain-map.attlist &=
|
|||||||
request-matcher?
|
request-matcher?
|
||||||
|
|
||||||
filter-chain =
|
filter-chain =
|
||||||
## Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom.
|
## Used within to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are assembled in a list in order to configure a FilterChainProxy, the most specific patterns must be placed at the top of the list, with most general ones at the bottom.
|
||||||
element filter-chain {filter-chain.attlist, empty}
|
element filter-chain {filter-chain.attlist, empty}
|
||||||
filter-chain.attlist &=
|
filter-chain.attlist &=
|
||||||
attribute pattern {xsd:token}
|
attribute pattern {xsd:token}
|
||||||
|
@ -974,11 +974,7 @@
|
|||||||
<xs:documentation>Used to explicitly configure a FilterChainProxy instance with a FilterChainMap</xs:documentation>
|
<xs:documentation>Used to explicitly configure a FilterChainProxy instance with a FilterChainMap</xs:documentation>
|
||||||
</xs:annotation><xs:complexType>
|
</xs:annotation><xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element maxOccurs="unbounded" name="filter-chain"><xs:annotation>
|
<xs:element maxOccurs="unbounded" ref="security:filter-chain"/>
|
||||||
<xs:documentation>Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom.</xs:documentation>
|
|
||||||
</xs:annotation><xs:complexType>
|
|
||||||
<xs:attributeGroup ref="security:filter-chain.attlist"/>
|
|
||||||
</xs:complexType></xs:element>
|
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
<xs:attributeGroup ref="security:filter-chain-map.attlist"/>
|
<xs:attributeGroup ref="security:filter-chain-map.attlist"/>
|
||||||
</xs:complexType></xs:element>
|
</xs:complexType></xs:element>
|
||||||
@ -1004,7 +1000,11 @@
|
|||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
</xs:attributeGroup>
|
</xs:attributeGroup>
|
||||||
|
<xs:element name="filter-chain"><xs:annotation>
|
||||||
|
<xs:documentation>Used within to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are assembled in a list in order to configure a FilterChainProxy, the most specific patterns must be placed at the top of the list, with most general ones at the bottom.</xs:documentation>
|
||||||
|
</xs:annotation><xs:complexType>
|
||||||
|
<xs:attributeGroup ref="security:filter-chain.attlist"/>
|
||||||
|
</xs:complexType></xs:element>
|
||||||
<xs:attributeGroup name="filter-chain.attlist">
|
<xs:attributeGroup name="filter-chain.attlist">
|
||||||
<xs:attribute name="pattern" use="required" type="xs:token"/>
|
<xs:attribute name="pattern" use="required" type="xs:token"/>
|
||||||
<xs:attribute name="filters" use="required" type="xs:token"/>
|
<xs:attribute name="filters" use="required" type="xs:token"/>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<xsl:output method="xml" indent="yes"/>
|
<xsl:output method="xml" indent="yes"/>
|
||||||
|
|
||||||
<xsl:variable name="elts-to-inline">
|
<xsl:variable name="elts-to-inline">
|
||||||
<xsl:text>,access-denied-handler,anonymous,session-management,concurrency-control,after-invocation-provider,authentication-provider,ldap-authentication-provider,user,port-mapping,openid-login,expression-handler,filter-chain,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,pre-post-annotation-handling,pre-invocation-advice,post-invocation-advice,invocation-attribute-factory,remember-me,salt-source,x509,</xsl:text>
|
<xsl:text>,access-denied-handler,anonymous,session-management,concurrency-control,after-invocation-provider,authentication-provider,ldap-authentication-provider,user,port-mapping,openid-login,expression-handler,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,pre-post-annotation-handling,pre-invocation-advice,post-invocation-advice,invocation-attribute-factory,remember-me,salt-source,x509,</xsl:text>
|
||||||
</xsl:variable>
|
</xsl:variable>
|
||||||
|
|
||||||
<xsl:template match="xs:element">
|
<xsl:template match="xs:element">
|
||||||
|
@ -4,6 +4,8 @@ import org.springframework.beans.factory.parsing.BeanDefinitionParsingException
|
|||||||
import org.springframework.security.config.BeanIds
|
import org.springframework.security.config.BeanIds
|
||||||
import org.springframework.security.web.FilterChainProxy
|
import org.springframework.security.web.FilterChainProxy
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
|
import org.springframework.beans.factory.BeanCreationException
|
||||||
|
import org.springframework.security.web.SecurityFilterChain
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests scenarios with multiple <http> elements.
|
* Tests scenarios with multiple <http> elements.
|
||||||
@ -22,11 +24,11 @@ class MultiHttpBlockConfigTests extends AbstractHttpConfigTests {
|
|||||||
}
|
}
|
||||||
createAppContext()
|
createAppContext()
|
||||||
FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
|
FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
|
||||||
Map filterChains = fcp.getFilterChainMap();
|
def filterChains = fcp.getFilterChains();
|
||||||
|
|
||||||
then:
|
then:
|
||||||
filterChains.size() == 2
|
filterChains.size() == 2
|
||||||
(filterChains.keySet() as List)[0].pattern == '/stateless/**'
|
filterChains[0].requestMatcher.pattern == '/stateless/**'
|
||||||
}
|
}
|
||||||
|
|
||||||
def duplicateHttpElementsAreRejected () {
|
def duplicateHttpElementsAreRejected () {
|
||||||
@ -39,7 +41,8 @@ class MultiHttpBlockConfigTests extends AbstractHttpConfigTests {
|
|||||||
}
|
}
|
||||||
createAppContext()
|
createAppContext()
|
||||||
then:
|
then:
|
||||||
thrown(BeanDefinitionParsingException)
|
BeanCreationException e = thrown()
|
||||||
|
e.cause.cause instanceof IllegalArgumentException
|
||||||
}
|
}
|
||||||
|
|
||||||
def duplicatePatternsAreRejected () {
|
def duplicatePatternsAreRejected () {
|
||||||
@ -52,7 +55,8 @@ class MultiHttpBlockConfigTests extends AbstractHttpConfigTests {
|
|||||||
}
|
}
|
||||||
createAppContext()
|
createAppContext()
|
||||||
then:
|
then:
|
||||||
thrown(BeanDefinitionParsingException)
|
BeanCreationException e = thrown()
|
||||||
|
e.cause instanceof IllegalArgumentException
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -64,9 +68,8 @@ class MultiHttpBlockConfigTests extends AbstractHttpConfigTests {
|
|||||||
'form-login'()
|
'form-login'()
|
||||||
}
|
}
|
||||||
createAppContext()
|
createAppContext()
|
||||||
def fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
|
FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
|
||||||
List filterChains = fcp.getFilterChainMap().values() as List;
|
SecurityFilterChain basicChain = fcp.filterChains[0];
|
||||||
List basicChain = filterChains[0];
|
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
Assert.assertSame (basicChain, appContext.getBean('basic'))
|
Assert.assertSame (basicChain, appContext.getBean('basic'))
|
||||||
|
@ -34,6 +34,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
|
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
|
||||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||||
@ -109,10 +110,10 @@ public class FilterChainProxyConfigTests {
|
|||||||
public void mixingPatternsAndPlaceholdersDoesntCauseOrderingIssues() throws Exception {
|
public void mixingPatternsAndPlaceholdersDoesntCauseOrderingIssues() throws Exception {
|
||||||
FilterChainProxy fcp = appCtx.getBean("sec1235FilterChainProxy", FilterChainProxy.class);
|
FilterChainProxy fcp = appCtx.getBean("sec1235FilterChainProxy", FilterChainProxy.class);
|
||||||
|
|
||||||
RequestMatcher[] matchers = fcp.getFilterChainMap().keySet().toArray(new RequestMatcher[fcp.getFilterChainMap().keySet().size()]);
|
List<SecurityFilterChain> chains = fcp.getFilterChains();
|
||||||
assertEquals("/login*", ((AntPathRequestMatcher)matchers[0]).getPattern());
|
assertEquals("/login*", ((AntPathRequestMatcher)chains.get(0).getRequestMatcher()).getPattern());
|
||||||
assertEquals("/logout", ((AntPathRequestMatcher)matchers[1]).getPattern());
|
assertEquals("/logout", ((AntPathRequestMatcher)chains.get(1).getRequestMatcher()).getPattern());
|
||||||
assertTrue(matchers[2] instanceof AnyRequestMatcher);
|
assertTrue(chains.get(2).getRequestMatcher() instanceof AnyRequestMatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) throws Exception {
|
private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) throws Exception {
|
||||||
|
@ -43,13 +43,21 @@ public class InvalidConfigurationTests {
|
|||||||
try {
|
try {
|
||||||
setContext("<http auto-config='true' />");
|
setContext("<http auto-config='true' />");
|
||||||
} catch (BeanCreationException e) {
|
} catch (BeanCreationException e) {
|
||||||
assertTrue(e.getCause().getCause() instanceof NoSuchBeanDefinitionException);
|
Throwable cause = ultimateCause(e);
|
||||||
NoSuchBeanDefinitionException nsbe = (NoSuchBeanDefinitionException) e.getCause().getCause();
|
assertTrue(cause instanceof NoSuchBeanDefinitionException);
|
||||||
|
NoSuchBeanDefinitionException nsbe = (NoSuchBeanDefinitionException) cause;
|
||||||
assertEquals(BeanIds.AUTHENTICATION_MANAGER, nsbe.getBeanName());
|
assertEquals(BeanIds.AUTHENTICATION_MANAGER, nsbe.getBeanName());
|
||||||
assertTrue(nsbe.getMessage().endsWith(AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE));
|
assertTrue(nsbe.getMessage().endsWith(AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Throwable ultimateCause(Throwable e) {
|
||||||
|
if (e.getCause() == null) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
return ultimateCause(e.getCause());
|
||||||
|
}
|
||||||
|
|
||||||
private void setContext(String context) {
|
private void setContext(String context) {
|
||||||
appContext = new InMemoryXmlApplicationContext(context);
|
appContext = new InMemoryXmlApplicationContext(context);
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,12 @@
|
|||||||
-->
|
-->
|
||||||
<beans default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans"
|
<beans default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans"
|
||||||
xmlns:sec="http://www.springframework.org/schema/security"
|
xmlns:sec="http://www.springframework.org/schema/security"
|
||||||
|
xmlns:util="http://www.springframework.org/schema/util"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
xsi:schemaLocation="
|
||||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||||
|
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
|
||||||
|
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
|
||||||
|
|
||||||
<bean id="mockFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>
|
<bean id="mockFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>
|
||||||
|
|
||||||
@ -45,44 +48,52 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
|
|||||||
<bean id="mockNotAFilter" class="org.springframework.security.web.util.AnyRequestMatcher"/>
|
<bean id="mockNotAFilter" class="org.springframework.security.web.util.AnyRequestMatcher"/>
|
||||||
|
|
||||||
<bean id="filterChain" class="org.springframework.security.web.FilterChainProxy">
|
<bean id="filterChain" class="org.springframework.security.web.FilterChainProxy">
|
||||||
<sec:filter-chain-map path-type="ant">
|
<constructor-arg>
|
||||||
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
<util:list>
|
||||||
<sec:filter-chain pattern="/some/other/path/**" filters="mockFilter"/>
|
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
||||||
<sec:filter-chain pattern="/do/not/filter" filters="none"/>
|
<sec:filter-chain pattern="/some/other/path/**" filters="mockFilter"/>
|
||||||
</sec:filter-chain-map>
|
<sec:filter-chain pattern="/do/not/filter" filters="none"/>
|
||||||
|
</util:list>
|
||||||
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- TODO: Refactor to replace the above (SEC-1034: 'new' is now the only valid syntax) -->
|
<!-- TODO: Refactor to replace the above (SEC-1034: 'new' is now the only valid syntax) -->
|
||||||
<bean id="newFilterChainProxy" class="org.springframework.security.web.FilterChainProxy">
|
<bean id="newFilterChainProxy" class="org.springframework.security.web.FilterChainProxy">
|
||||||
<sec:filter-chain-map path-type="ant">
|
<constructor-arg>
|
||||||
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
<util:list>
|
||||||
<sec:filter-chain pattern="/some/other/path/**"
|
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
||||||
filters="
|
<sec:filter-chain pattern="/some/other/path/**"
|
||||||
sif,
|
filters="
|
||||||
mockFilter,
|
sif,
|
||||||
mockFilter2"
|
mockFilter,
|
||||||
/>
|
mockFilter2"
|
||||||
<sec:filter-chain pattern="/do/not/filter" filters="none"/>
|
/>
|
||||||
<sec:filter-chain pattern="/**" filters="sif,apf,mockFilter"/>
|
<sec:filter-chain pattern="/do/not/filter" filters="none"/>
|
||||||
</sec:filter-chain-map>
|
<sec:filter-chain pattern="/**" filters="sif,apf,mockFilter"/>
|
||||||
|
</util:list>
|
||||||
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="newFilterChainProxyNoDefaultPath" class="org.springframework.security.web.FilterChainProxy">
|
<bean id="newFilterChainProxyNoDefaultPath" class="org.springframework.security.web.FilterChainProxy">
|
||||||
<sec:filter-chain-map path-type="ant">
|
<constructor-arg>
|
||||||
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
<util:list>
|
||||||
<sec:filter-chain pattern="/*.bar" filters="mockFilter,mockFilter2"/>
|
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
||||||
</sec:filter-chain-map>
|
<sec:filter-chain pattern="/*.bar" filters="mockFilter,mockFilter2"/>
|
||||||
|
</util:list>
|
||||||
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="newFilterChainProxyWrongPathOrder" class="org.springframework.security.web.FilterChainProxy">
|
<bean id="newFilterChainProxyWrongPathOrder" class="org.springframework.security.web.FilterChainProxy">
|
||||||
<sec:filter-chain-map path-type="ant">
|
<constructor-arg>
|
||||||
|
<util:list>
|
||||||
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
||||||
<sec:filter-chain pattern="/**" filters="
|
<sec:filter-chain pattern="/**" filters="
|
||||||
sif,
|
sif,
|
||||||
apf,
|
apf,
|
||||||
mockFilter"/>
|
mockFilter"/>
|
||||||
<sec:filter-chain pattern="/some/other/path/**" filters="sif,mockFilter,mockFilter2"/>
|
<sec:filter-chain pattern="/some/other/path/**" filters="sif,mockFilter,mockFilter2"/>
|
||||||
</sec:filter-chain-map>
|
</util:list>
|
||||||
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="newFilterChainProxyRegex" class="org.springframework.security.web.FilterChainProxy">
|
<bean id="newFilterChainProxyRegex" class="org.springframework.security.web.FilterChainProxy">
|
||||||
@ -97,60 +108,70 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
|
|||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
|
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
|
||||||
|
|
||||||
<bean id="sec1235FilterChainProxy" class="org.springframework.security.web.FilterChainProxy">
|
<bean id="sec1235FilterChainProxy" class="org.springframework.security.web.FilterChainProxy">
|
||||||
<sec:filter-chain-map path-type="ant">
|
<constructor-arg>
|
||||||
<sec:filter-chain pattern="${sec1235.pattern1}*" filters="sif,apf,mockFilter"/>
|
<util:list>
|
||||||
<sec:filter-chain pattern="${sec1235.pattern2}" filters="mockFilter2"/>
|
<sec:filter-chain pattern="${sec1235.pattern1}*" filters="sif,apf,mockFilter"/>
|
||||||
<sec:filter-chain pattern="/**" filters="sif"/>
|
<sec:filter-chain pattern="${sec1235.pattern2}" filters="mockFilter2"/>
|
||||||
</sec:filter-chain-map>
|
<sec:filter-chain pattern="/**" filters="sif"/>
|
||||||
|
</util:list>
|
||||||
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="newFilterChainProxyNonNamespace" class="org.springframework.security.web.FilterChainProxy">
|
<bean id="newFilterChainProxyNonNamespace" class="org.springframework.security.web.FilterChainProxy">
|
||||||
<property name="filterChainMap">
|
<constructor-arg>
|
||||||
<map>
|
<list>
|
||||||
<entry>
|
<bean class="org.springframework.security.web.SecurityFilterChain">
|
||||||
<key>
|
<constructor-arg>
|
||||||
<bean class="org.springframework.security.web.util.AntPathRequestMatcher">
|
<bean class="org.springframework.security.web.util.AntPathRequestMatcher">
|
||||||
<constructor-arg value="/foo/**"/>
|
<constructor-arg value="/foo/**"/>
|
||||||
</bean>
|
</bean>
|
||||||
</key>
|
</constructor-arg>
|
||||||
<list>
|
<constructor-arg>
|
||||||
<ref local="mockFilter"/>
|
<list>
|
||||||
</list>
|
<ref local="mockFilter"/>
|
||||||
</entry>
|
</list>
|
||||||
<entry>
|
</constructor-arg>
|
||||||
<key>
|
</bean>
|
||||||
|
<bean class="org.springframework.security.web.SecurityFilterChain">
|
||||||
|
<constructor-arg>
|
||||||
<bean class="org.springframework.security.web.util.AntPathRequestMatcher">
|
<bean class="org.springframework.security.web.util.AntPathRequestMatcher">
|
||||||
<constructor-arg value="/some/other/path/**"/>
|
<constructor-arg value="/some/other/path/**"/>
|
||||||
</bean>
|
</bean>
|
||||||
</key>
|
</constructor-arg>
|
||||||
<list>
|
<constructor-arg>
|
||||||
<ref local="sif"/>
|
<list>
|
||||||
<ref local="mockFilter"/>
|
<ref local="sif"/>
|
||||||
<ref local="mockFilter2"/>
|
<ref local="mockFilter"/>
|
||||||
</list>
|
<ref local="mockFilter2"/>
|
||||||
</entry>
|
</list>
|
||||||
<entry>
|
</constructor-arg>
|
||||||
<key>
|
</bean>
|
||||||
|
<bean class="org.springframework.security.web.SecurityFilterChain">
|
||||||
|
<constructor-arg>
|
||||||
<bean class="org.springframework.security.web.util.AntPathRequestMatcher">
|
<bean class="org.springframework.security.web.util.AntPathRequestMatcher">
|
||||||
<constructor-arg value="/do/not/filter*"/>
|
<constructor-arg value="/do/not/filter*"/>
|
||||||
</bean>
|
</bean>
|
||||||
</key>
|
</constructor-arg>
|
||||||
<list/>
|
<constructor-arg>
|
||||||
</entry>
|
<list />
|
||||||
<entry>
|
</constructor-arg>
|
||||||
<key>
|
</bean>
|
||||||
|
<bean class="org.springframework.security.web.SecurityFilterChain">
|
||||||
|
<constructor-arg>
|
||||||
<bean class="org.springframework.security.web.util.AntPathRequestMatcher">
|
<bean class="org.springframework.security.web.util.AntPathRequestMatcher">
|
||||||
<constructor-arg value="/**"/>
|
<constructor-arg value="/**"/>
|
||||||
</bean>
|
</bean>
|
||||||
</key>
|
</constructor-arg>
|
||||||
<list>
|
<constructor-arg>
|
||||||
<ref local="sif"/>
|
<list>
|
||||||
<ref local="apf"/>
|
<ref local="sif"/>
|
||||||
<ref local="mockFilter"/>
|
<ref local="apf"/>
|
||||||
</list>
|
<ref local="mockFilter"/>
|
||||||
</entry>
|
</list>
|
||||||
</map>
|
</constructor-arg>
|
||||||
</property>
|
</bean>
|
||||||
|
</list>
|
||||||
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@ -32,7 +32,7 @@ public final class SecurityFilterChain {
|
|||||||
|
|
||||||
public SecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
|
public SecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
|
||||||
this.requestMatcher = requestMatcher;
|
this.requestMatcher = requestMatcher;
|
||||||
this.filters = filters;
|
this.filters = new ArrayList<Filter>(filters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RequestMatcher getRequestMatcher() {
|
public RequestMatcher getRequestMatcher() {
|
||||||
|
@ -14,4 +14,13 @@ public final class AnyRequestMatcher implements RequestMatcher {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return obj instanceof AnyRequestMatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user