SEC-640: Add namespace support for FilterInvocationDefinitionSource configuration

http://jira.springframework.org/browse/SEC-640
This commit is contained in:
Luke Taylor 2008-02-28 19:29:33 +00:00
parent 1bc863fce1
commit 33023565a8
14 changed files with 304 additions and 99 deletions

View File

@ -34,4 +34,5 @@ abstract class Elements {
public static final String CUSTOM_FILTER = "custom-filter";
public static final String CUSTOM_AUTH_RPOVIDER = "custom-authentication-provider";
public static final String X509 = "x509";
public static final String FILTER_INVOCATION_DEFINITION_SOURCE = "filter-invocation-definition-source";
}

View File

@ -0,0 +1,54 @@
package org.springframework.security.config;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.util.AntUrlPathMatcher;
import org.springframework.security.util.UrlMatcher;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Allows for convenient creation of a {@link FilterInvocationDefinitionSource} bean for use with a FilterSecurityInterceptor.
*
* @author Luke Taylor
* @version $Id$
*/
public class FilterInvocationDefinitionSourceBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
protected String getBeanClassName(Element element) {
return "org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource";
}
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
List interceptUrls = DomUtils.getChildElementsByTagName(element, "intercept-url");
// Check for attributes that aren't allowed in this context
Iterator interceptUrlElts = interceptUrls.iterator();
while(interceptUrlElts.hasNext()) {
Element elt = (Element) interceptUrlElts.next();
if (StringUtils.hasLength(elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL))) {
parserContext.getReaderContext().error("The attribute '" + HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL + "' isn't allowed here.", elt);
}
if (StringUtils.hasLength(elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS))) {
parserContext.getReaderContext().error("The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS + "' isn't allowed here.", elt);
}
}
UrlMatcher matcher = HttpSecurityBeanDefinitionParser.createUrlMatcher(element);
boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
LinkedHashMap requestMap = new LinkedHashMap();
HttpSecurityBeanDefinitionParser.parseInterceptUrlsForFilterInvocationRequestMap(interceptUrls, requestMap,
convertPathsToLowerCase, parserContext);
builder.addConstructorArg(matcher);
builder.addConstructorArg(requestMap);
}
}

View File

@ -20,6 +20,7 @@ import org.springframework.security.wrapper.SecurityContextHolderAwareRequestFil
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource;
import org.springframework.security.intercept.web.FilterSecurityInterceptor;
import org.springframework.security.intercept.web.RequestKey;
import org.springframework.security.securechannel.ChannelDecisionManagerImpl;
import org.springframework.security.securechannel.ChannelProcessingFilter;
import org.springframework.security.securechannel.InsecureChannelProcessor;
@ -111,45 +112,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
= BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
Map filterChainMap = new LinkedHashMap();
String patternType = element.getAttribute(ATT_PATH_TYPE);
if (!StringUtils.hasText(patternType)) {
patternType = DEF_PATH_TYPE_ANT;
}
boolean useRegex = patternType.equals(OPT_PATH_TYPE_REGEX);
UrlMatcher matcher = new AntUrlPathMatcher();
if (useRegex) {
matcher = new RegexUrlPathMatcher();
}
// Deal with lowercase conversion requests
String lowercaseComparisons = element.getAttribute(ATT_LOWERCASE_COMPARISONS);
if (!StringUtils.hasText(lowercaseComparisons)) {
lowercaseComparisons = null;
}
// Only change from the defaults if the attribute has been set
if ("true".equals(lowercaseComparisons)) {
if (useRegex) {
((RegexUrlPathMatcher)matcher).setRequiresLowerCaseUrl(true);
}
// Default for ant is already to force lower case
} else if ("false".equals(lowercaseComparisons)) {
if (!useRegex) {
((AntUrlPathMatcher)matcher).setRequiresLowerCaseUrl(false);
}
// Default for regex is no change
}
DefaultFilterInvocationDefinitionSource interceptorFilterInvDefSource =
new DefaultFilterInvocationDefinitionSource(matcher);
DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
new DefaultFilterInvocationDefinitionSource(matcher);
UrlMatcher matcher = createUrlMatcher(element);
filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher);
// Add servlet-api integration filter if required
@ -164,8 +129,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
filterSecurityInterceptorBuilder.addPropertyValue("objectDefinitionSource", interceptorFilterInvDefSource);
// Set up the access manager and authentication mananger references for http
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
@ -182,13 +145,26 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
// SEC-501 - should paths stored in request maps be converted to lower case
// true if Ant path and using lower case
boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
parseInterceptUrls(DomUtils.getChildElementsByTagName(element, "intercept-url"),
filterChainMap, interceptorFilterInvDefSource, channelFilterInvDefSource,
LinkedHashMap channelRequestMap = new LinkedHashMap();
LinkedHashMap filterInvocationDefinitionMap = new LinkedHashMap();
List interceptUrlElts = DomUtils.getChildElementsByTagName(element, "intercept-url");
parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
convertPathsToLowerCase, parserContext);
parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, filterInvocationDefinitionMap,
convertPathsToLowerCase, parserContext);
DefaultFilterInvocationDefinitionSource interceptorFilterInvDefSource =
new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap);
DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap);
filterSecurityInterceptorBuilder.addPropertyValue("objectDefinitionSource", interceptorFilterInvDefSource);
// Check if we need to register the channel processing beans
if (((DefaultFilterInvocationDefinitionSource)channelFilterInvDefSource).getMapSize() > 0) {
if (channelRequestMap.size() > 0) {
// At least one channel requirement has been specified
RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager",
@ -271,18 +247,103 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
return null;
}
static UrlMatcher createUrlMatcher(Element element) {
String patternType = element.getAttribute(ATT_PATH_TYPE);
if (!StringUtils.hasText(patternType)) {
patternType = DEF_PATH_TYPE_ANT;
}
boolean useRegex = patternType.equals(OPT_PATH_TYPE_REGEX);
UrlMatcher matcher = new AntUrlPathMatcher();
if (useRegex) {
matcher = new RegexUrlPathMatcher();
}
// Deal with lowercase conversion requests
String lowercaseComparisons = element.getAttribute(ATT_LOWERCASE_COMPARISONS);
if (!StringUtils.hasText(lowercaseComparisons)) {
lowercaseComparisons = null;
}
// Only change from the defaults if the attribute has been set
if ("true".equals(lowercaseComparisons)) {
if (useRegex) {
((RegexUrlPathMatcher)matcher).setRequiresLowerCaseUrl(true);
}
// Default for ant is already to force lower case
} else if ("false".equals(lowercaseComparisons)) {
if (!useRegex) {
((AntUrlPathMatcher)matcher).setRequiresLowerCaseUrl(false);
}
// Default for regex is no change
}
return matcher;
}
/**
* Parses the intercept-url elements and populates the FilterChainProxy's filter chain Map and the
* FilterInvocationDefinitionSource used in FilterSecurityInterceptor.
* map used to create the FilterInvocationDefintionSource for the FilterSecurityInterceptor.
*/
private void parseInterceptUrls(List urlElts, Map filterChainMap,
DefaultFilterInvocationDefinitionSource interceptorFilterInvDefSource,
DefaultFilterInvocationDefinitionSource channelFilterInvDefSource,
void parseInterceptUrlsForChannelSecurityAndFilterChain(List urlElts, Map filterChainMap, Map channelRequestMap,
boolean useLowerCasePaths, ParserContext parserContext) {
Iterator urlEltsIterator = urlElts.iterator();
ConfigAttributeEditor editor = new ConfigAttributeEditor();
while (urlEltsIterator.hasNext()) {
Element urlElt = (Element) urlEltsIterator.next();
String path = urlElt.getAttribute(ATT_PATH_PATTERN);
if(!StringUtils.hasText(path)) {
parserContext.getReaderContext().error("path attribute cannot be empty or null", urlElt);
}
if (useLowerCasePaths) {
path = path.toLowerCase();
}
String requiredChannel = urlElt.getAttribute(ATT_REQUIRES_CHANNEL);
if (StringUtils.hasText(requiredChannel)) {
String channelConfigAttribute = null;
if (requiredChannel.equals(OPT_REQUIRES_HTTPS)) {
channelConfigAttribute = "REQUIRES_SECURE_CHANNEL";
} else if (requiredChannel.equals(OPT_REQUIRES_HTTP)) {
channelConfigAttribute = "REQUIRES_INSECURE_CHANNEL";
} else if (requiredChannel.equals(OPT_ANY_CHANNEL)) {
channelConfigAttribute = ChannelDecisionManagerImpl.ANY_CHANNEL;
} else {
parserContext.getReaderContext().error("Unsupported channel " + requiredChannel, urlElt);
}
editor.setAsText(channelConfigAttribute);
channelRequestMap.put(new RequestKey(path), (ConfigAttributeDefinition) editor.getValue());
}
String filters = urlElt.getAttribute(ATT_FILTERS);
if (StringUtils.hasText(filters)) {
if (!filters.equals(OPT_FILTERS_NONE)) {
parserContext.getReaderContext().error("Currently only 'none' is supported as the custom " +
"filters attribute", urlElt);
}
filterChainMap.put(path, Collections.EMPTY_LIST);
}
}
}
static void parseInterceptUrlsForFilterInvocationRequestMap(List urlElts, Map filterInvocationDefinitionMap,
boolean useLowerCasePaths, ParserContext parserContext) {
Iterator urlEltsIterator = urlElts.iterator();
ConfigAttributeEditor editor = new ConfigAttributeEditor();
while (urlEltsIterator.hasNext()) {
@ -308,38 +369,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
// Convert the comma-separated list of access attributes to a ConfigAttributeDefinition
if (StringUtils.hasText(access)) {
editor.setAsText(access);
interceptorFilterInvDefSource.addSecureUrl(path, method, (ConfigAttributeDefinition) editor.getValue());
}
String requiredChannel = urlElt.getAttribute(ATT_REQUIRES_CHANNEL);
if (StringUtils.hasText(requiredChannel)) {
String channelConfigAttribute = null;
if (requiredChannel.equals(OPT_REQUIRES_HTTPS)) {
channelConfigAttribute = "REQUIRES_SECURE_CHANNEL";
} else if (requiredChannel.equals(OPT_REQUIRES_HTTP)) {
channelConfigAttribute = "REQUIRES_INSECURE_CHANNEL";
} else if (requiredChannel.equals(OPT_ANY_CHANNEL)) {
channelConfigAttribute = ChannelDecisionManagerImpl.ANY_CHANNEL;
} else {
parserContext.getReaderContext().error("Unsupported channel " + requiredChannel, urlElt);
}
editor.setAsText(channelConfigAttribute);
channelFilterInvDefSource.addSecureUrl(path, (ConfigAttributeDefinition) editor.getValue());
}
String filters = urlElt.getAttribute(ATT_FILTERS);
if (StringUtils.hasText(filters)) {
if (!filters.equals(OPT_FILTERS_NONE)) {
parserContext.getReaderContext().error("Currently only 'none' is supported as the custom " +
"filters attribute", urlElt);
}
filterChainMap.put(path, Collections.EMPTY_LIST);
filterInvocationDefinitionMap.put(new RequestKey(path, method), editor.getValue());
}
}
}
}

View File

@ -23,6 +23,7 @@ public class SecurityNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser());
registerBeanDefinitionParser(Elements.ANNOTATION_DRIVEN, new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser());
registerBeanDefinitionParser(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationDefinitionSourceBeanDefinitionParser());
// Decorators
registerBeanDefinitionDecorator(Elements.INTERCEPT_METHODS, new InterceptMethodsBeanDefinitionDecorator());

View File

@ -61,7 +61,7 @@ public class DefaultFilterInvocationDefinitionSource implements FilterInvocation
/**
* Non method-specific map of URL patterns to <tt>ConfigAttributeDefinition</tt>s
* TODO: Store in the httpMethod map with null key.
* TODO: Store in the httpMethod map with null key.
*/
private Map requestMap = new LinkedHashMap();
/** Stores request maps keyed by specific HTTP methods */
@ -75,10 +75,18 @@ public class DefaultFilterInvocationDefinitionSource implements FilterInvocation
* Creates a FilterInvocationDefinitionSource with the supplied URL matching strategy.
* @param urlMatcher
*/
public DefaultFilterInvocationDefinitionSource(UrlMatcher urlMatcher) {
DefaultFilterInvocationDefinitionSource(UrlMatcher urlMatcher) {
this.urlMatcher = urlMatcher;
}
/**
* Builds the internal request map from the supplied map. The key elements should be of type {@link RequestKey},
* which contains a URL path and an optional HTTP method (may be null). The path stored in the key will depend on
* the type of the supplied UrlMatcher.
*
* @param urlMatcher typically an ant or regular expression matcher.
* @param requestMap order-preserving map of <RequestKey, ConfigAttributeDefinition>.
*/
public DefaultFilterInvocationDefinitionSource(UrlMatcher urlMatcher, LinkedHashMap requestMap) {
this.urlMatcher = urlMatcher;
@ -86,13 +94,14 @@ public class DefaultFilterInvocationDefinitionSource implements FilterInvocation
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
addSecureUrl((String)entry.getKey(), (ConfigAttributeDefinition)entry.getValue());
RequestKey reqKey = (RequestKey) entry.getKey();
addSecureUrl(reqKey.getUrl(), reqKey.getMethod(), (ConfigAttributeDefinition) entry.getValue());
}
}
//~ Methods ========================================================================================================
public void addSecureUrl(String pattern, ConfigAttributeDefinition attr) {
void addSecureUrl(String pattern, ConfigAttributeDefinition attr) {
addSecureUrl(pattern, null, attr);
}
@ -102,7 +111,7 @@ public class DefaultFilterInvocationDefinitionSource implements FilterInvocation
* to the request map and will be passed back to the <tt>UrlMatcher</tt> when iterating through the map to find
* a match for a particular URL.
*/
public void addSecureUrl(String pattern, String method, ConfigAttributeDefinition attr) {
void addSecureUrl(String pattern, String method, ConfigAttributeDefinition attr) {
Map mapToUse = getRequestMapForHttpMethod(method);
mapToUse.put(urlMatcher.compile(pattern), attr);

View File

@ -167,7 +167,7 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor
String[] tokens = StringUtils.commaDelimitedListToStringArray(value);
urlMap.put(name, new ConfigAttributeDefinition(tokens));
urlMap.put(new RequestKey(name), new ConfigAttributeDefinition(tokens));
}
DefaultFilterInvocationDefinitionSource fids =

View File

@ -5,25 +5,35 @@ package org.springframework.security.intercept.web;
* @version $Id$
*/
public class RequestKey {
String url;
String method;
private String url;
private String method;
public RequestKey(String url) {
this(url, "");
this(url, null);
}
public RequestKey(String url, String method) {
this.url = url;
this.method = method;
}
String getUrl() {
return url;
}
String getMethod() {
return method;
}
public int hashCode() {
int code = 31;
code ^= url.hashCode();
code ^= method.hashCode();
if (method != null) {
code ^= method.hashCode();
}
return code;
}
public boolean equals(Object obj) {
@ -33,6 +43,14 @@ public class RequestKey {
RequestKey key = (RequestKey) obj;
return url.equals(key.url) && method.equals(key.method);
if (!url.equals(key.url)) {
return false;
}
if (method == null && key.method != null) {
return false;
}
return method.equals(key.method);
}
}

View File

@ -3,7 +3,7 @@ package org.springframework.security.util;
/**
* Strategy for deciding whether configured path matches a submitted candidate URL.
*
* @author luke
* @author Luke Taylor
* @version $Id$
* @since 2.0
*/

View File

@ -212,6 +212,18 @@ filter-chain.attlist &=
filter-chain.attlist &=
attribute filters {xsd:string}
filter-invocation-definition-source =
## Used to explicitly configure a FilterInvocationDefinitionSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error.
element filter-invocation-definition-source {fids.attlist, intercept-url+}
fids.attlist &=
id?
fids.attlist &=
## as for http element
attribute lowercase-comparisons {"true" | "false"}?
fids.attlist &=
## as for http element
path-type?
http-basic =
## Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)
element http-basic {empty}
@ -328,6 +340,6 @@ before =
## The filter immediately before which the custom-filter should be placed in the chain
attribute before {"FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SESSION_CONTEXT_INTEGRATION_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_PROCESSING_FILTER" | "AUTHENTICATION_PROCESSING_FILTER" | "BASIC_PROCESSING_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "NTLM_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER"}

View File

@ -527,6 +527,46 @@
<xs:attribute name="pattern" use="required" type="xs:string"/>
<xs:attribute name="filters" use="required" type="xs:string"/>
</xs:attributeGroup>
<xs:element name="filter-invocation-definition-source">
<xs:annotation>
<xs:documentation>Used to explicitly configure a FilterInvocationDefinitionSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the &lt;http&gt; element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error. </xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="security:intercept-url"/>
</xs:sequence>
<xs:attributeGroup ref="security:fids.attlist"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="fids.attlist">
<xs:attribute name="id" type="xs:ID">
<xs:annotation>
<xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="lowercase-comparisons">
<xs:annotation>
<xs:documentation>as for http element</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="true"/>
<xs:enumeration value="false"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="path-type">
<xs:annotation>
<xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="ant"/>
<xs:enumeration value="regex"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="http-basic">
<xs:annotation>
<xs:documentation>Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>

View File

@ -38,7 +38,7 @@ import java.util.List;
*/
public class HttpSecurityBeanDefinitionParserTests {
private AbstractXmlApplicationContext appContext;
private static final String AUTH_PROVIDER_XML =
static final String AUTH_PROVIDER_XML =
" <authentication-provider>" +
" <user-service>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +

View File

@ -19,6 +19,7 @@ import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.MockFilterChain;
import org.springframework.security.SecurityConfig;
import org.springframework.security.util.AntUrlPathMatcher;
import org.springframework.security.util.InMemoryXmlApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@ -169,6 +170,38 @@ public class DefaultFilterInvocationDefinitionSourceTests {
response = map.lookupAttributes(fi.getRequestUrl());
assertEquals(def, response);
}
@Test
public void xmlMapConfigurationIsSuccessful() {
InMemoryXmlApplicationContext context = new InMemoryXmlApplicationContext(
"<b:bean id='fids' class='org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource'>" +
" <b:constructor-arg>" +
" <b:bean class='org.springframework.security.util.AntUrlPathMatcher'/>" +
" </b:constructor-arg>" +
" <b:constructor-arg>" +
" <b:map>" +
" <b:entry>" +
" <b:key>" +
" <b:bean class='org.springframework.security.intercept.web.RequestKey'>" +
" <b:constructor-arg index='0' value='/**'/>" +
" <b:constructor-arg index='1' value='GET'/>" +
" </b:bean>" +
" </b:key>" +
" <b:bean class='org.springframework.security.ConfigAttributeDefinition'>" +
" <b:constructor-arg value='ROLE_A'/>" +
" </b:bean>" +
" </b:entry>" +
" </b:map>" +
" </b:constructor-arg>" +
"</b:bean>"
);
DefaultFilterInvocationDefinitionSource fids = (DefaultFilterInvocationDefinitionSource) context.getBean("fids");
ConfigAttributeDefinition cad = fids.lookupAttributes("/anything", "GET");
assertNotNull(cad);
assertEquals(1, cad.getConfigAttributes().size());
context.close();
}
private FilterInvocation createFilterInvocation(String path, String method) {
MockHttpServletRequest request = new MockHttpServletRequest();

View File

@ -39,6 +39,7 @@ import org.springframework.mock.web.MockHttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedHashMap;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
@ -220,9 +221,10 @@ public class FilterSecurityInterceptorTests extends TestCase {
}
public void testNotLoadedFromApplicationContext() throws Exception {
LinkedHashMap reqMap = new LinkedHashMap();
reqMap.put(new RequestKey("/secure/**", null), new ConfigAttributeDefinition(new String[] {"ROLE_USER"}));
DefaultFilterInvocationDefinitionSource fids
= new DefaultFilterInvocationDefinitionSource(new AntUrlPathMatcher());
fids.addSecureUrl("/secure/**", null, new ConfigAttributeDefinition(new String[] {"ROLE_USER"}));
= new DefaultFilterInvocationDefinitionSource(new AntUrlPathMatcher());
FilterSecurityInterceptor filter = new FilterSecurityInterceptor();
filter.setObjectDefinitionSource(fids);

View File

@ -21,6 +21,7 @@ import org.springframework.security.MockFilterConfig;
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
import org.springframework.security.intercept.web.MockFilterInvocationDefinitionSource;
import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource;
import org.springframework.security.intercept.web.RequestKey;
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
import org.springframework.beans.factory.BeanCreationException;
@ -34,6 +35,7 @@ import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import java.util.LinkedHashMap;
import java.util.List;
/**
@ -80,9 +82,10 @@ public class FilterChainProxyTests {
ConfigAttributeDefinition cad = new ConfigAttributeDefinition(new MockConfigAttribute());
LinkedHashMap map = new LinkedHashMap();
map.put(new RequestKey("/**"), cad);
DefaultFilterInvocationDefinitionSource fids =
new DefaultFilterInvocationDefinitionSource(new AntUrlPathMatcher());
fids.addSecureUrl("/**", cad);
new DefaultFilterInvocationDefinitionSource(new AntUrlPathMatcher(), map);
filterChainProxy.setFilterInvocationDefinitionSource(fids);