diff --git a/core/src/main/java/org/springframework/security/config/Elements.java b/core/src/main/java/org/springframework/security/config/Elements.java
index 00b0e2e4ca..9b7ec7b5e6 100644
--- a/core/src/main/java/org/springframework/security/config/Elements.java
+++ b/core/src/main/java/org/springframework/security/config/Elements.java
@@ -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";
}
diff --git a/core/src/main/java/org/springframework/security/config/FilterInvocationDefinitionSourceBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/FilterInvocationDefinitionSourceBeanDefinitionParser.java
new file mode 100644
index 0000000000..f8cf00c7a7
--- /dev/null
+++ b/core/src/main/java/org/springframework/security/config/FilterInvocationDefinitionSourceBeanDefinitionParser.java
@@ -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);
+ }
+}
diff --git a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java
index 047224a962..7ff70ad094 100644
--- a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java
+++ b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java
@@ -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,52 @@ 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()) {
@@ -298,19 +308,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
path = path.toLowerCase();
}
- String method = urlElt.getAttribute(ATT_HTTP_METHOD);
- if (!StringUtils.hasText(method)) {
- method = null;
- }
-
- String access = urlElt.getAttribute(ATT_ACCESS_CONFIG);
-
- // 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)) {
@@ -327,9 +324,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
}
editor.setAsText(channelConfigAttribute);
- channelFilterInvDefSource.addSecureUrl(path, (ConfigAttributeDefinition) editor.getValue());
+ channelRequestMap.put(new RequestKey(path), (ConfigAttributeDefinition) editor.getValue());
}
-
+
String filters = urlElt.getAttribute(ATT_FILTERS);
if (StringUtils.hasText(filters)) {
@@ -342,4 +339,39 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
}
}
}
+
+ static void parseInterceptUrlsForFilterInvocationRequestMap(List urlElts, Map filterInvocationDefinitionMap,
+ 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 method = urlElt.getAttribute(ATT_HTTP_METHOD);
+ if (!StringUtils.hasText(method)) {
+ method = null;
+ }
+
+ String access = urlElt.getAttribute(ATT_ACCESS_CONFIG);
+
+ // Convert the comma-separated list of access attributes to a ConfigAttributeDefinition
+ if (StringUtils.hasText(access)) {
+ editor.setAsText(access);
+ filterInvocationDefinitionMap.put(new RequestKey(path, method), editor.getValue());
+ }
+ }
+ }
+
}
diff --git a/core/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java b/core/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java
index 2122750101..ed60e3bfb0 100644
--- a/core/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java
+++ b/core/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java
@@ -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());
diff --git a/core/src/main/java/org/springframework/security/intercept/web/DefaultFilterInvocationDefinitionSource.java b/core/src/main/java/org/springframework/security/intercept/web/DefaultFilterInvocationDefinitionSource.java
index 1ebb28b166..84dd0c289b 100644
--- a/core/src/main/java/org/springframework/security/intercept/web/DefaultFilterInvocationDefinitionSource.java
+++ b/core/src/main/java/org/springframework/security/intercept/web/DefaultFilterInvocationDefinitionSource.java
@@ -61,7 +61,7 @@ public class DefaultFilterInvocationDefinitionSource implements FilterInvocation
/**
* Non method-specific map of URL patterns to ConfigAttributeDefinitions
- * 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 .
+ */
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 UrlMatcher 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);
diff --git a/core/src/main/java/org/springframework/security/intercept/web/FilterInvocationDefinitionSourceEditor.java b/core/src/main/java/org/springframework/security/intercept/web/FilterInvocationDefinitionSourceEditor.java
index c0dac27947..c5bf09cba0 100644
--- a/core/src/main/java/org/springframework/security/intercept/web/FilterInvocationDefinitionSourceEditor.java
+++ b/core/src/main/java/org/springframework/security/intercept/web/FilterInvocationDefinitionSourceEditor.java
@@ -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 =
diff --git a/core/src/main/java/org/springframework/security/intercept/web/RequestKey.java b/core/src/main/java/org/springframework/security/intercept/web/RequestKey.java
index af3cb50da6..84e02e2186 100644
--- a/core/src/main/java/org/springframework/security/intercept/web/RequestKey.java
+++ b/core/src/main/java/org/springframework/security/intercept/web/RequestKey.java
@@ -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);
}
}
diff --git a/core/src/main/java/org/springframework/security/util/UrlMatcher.java b/core/src/main/java/org/springframework/security/util/UrlMatcher.java
index 0eee4b8710..8166717aa9 100644
--- a/core/src/main/java/org/springframework/security/util/UrlMatcher.java
+++ b/core/src/main/java/org/springframework/security/util/UrlMatcher.java
@@ -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
*/
diff --git a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc
index beeea6196d..e050cf91ae 100644
--- a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc
+++ b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc
@@ -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 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"}
-
+
diff --git a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd
index 0d2cf92a27..a30ebe7495 100644
--- a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd
+++ b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd
@@ -527,6 +527,46 @@
+
+
+ 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.
+
+
+
+
+
+
+
+
+
+
+
+ A bean identifier, used for referring to the bean elsewhere in the context.
+
+
+
+
+ as for http element
+
+
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
+
Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)
diff --git a/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java b/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java
index 91dc3bf58d..bdb578a304 100644
--- a/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java
+++ b/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java
@@ -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 =
" " +
" " +
" " +
diff --git a/core/src/test/java/org/springframework/security/intercept/web/DefaultFilterInvocationDefinitionSourceTests.java b/core/src/test/java/org/springframework/security/intercept/web/DefaultFilterInvocationDefinitionSourceTests.java
index 294b715782..4fa1566377 100644
--- a/core/src/test/java/org/springframework/security/intercept/web/DefaultFilterInvocationDefinitionSourceTests.java
+++ b/core/src/test/java/org/springframework/security/intercept/web/DefaultFilterInvocationDefinitionSourceTests.java
@@ -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(
+ "" +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ ""
+ );
+
+ 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();
diff --git a/core/src/test/java/org/springframework/security/intercept/web/FilterSecurityInterceptorTests.java b/core/src/test/java/org/springframework/security/intercept/web/FilterSecurityInterceptorTests.java
index f91b94509c..4e64c455da 100644
--- a/core/src/test/java/org/springframework/security/intercept/web/FilterSecurityInterceptorTests.java
+++ b/core/src/test/java/org/springframework/security/intercept/web/FilterSecurityInterceptorTests.java
@@ -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);
diff --git a/core/src/test/java/org/springframework/security/util/FilterChainProxyTests.java b/core/src/test/java/org/springframework/security/util/FilterChainProxyTests.java
index f3c03b59de..0dd2afd1e0 100644
--- a/core/src/test/java/org/springframework/security/util/FilterChainProxyTests.java
+++ b/core/src/test/java/org/springframework/security/util/FilterChainProxyTests.java
@@ -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);