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 6aa948b032..e9099e3ca3 100644 --- a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java @@ -94,6 +94,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_USER_SERVICE_REF = "user-service-ref"; static final String ATT_ENTRY_POINT_REF = "entry-point-ref"; + + static final String ATT_ONCE_PER_REQUEST = "once-per-request"; public BeanDefinition parse(Element element, ParserContext parserContext) { BeanDefinitionRegistry registry = parserContext.getRegistry(); @@ -156,6 +158,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { new RuntimeBeanReference(accessManagerId)); filterSecurityInterceptorBuilder.addPropertyValue("authenticationManager", ConfigUtils.registerProviderManagerIfNecessary(parserContext)); + + if ("true".equals(element.getAttribute(ATT_ONCE_PER_REQUEST))) { + filterSecurityInterceptorBuilder.addPropertyValue("observeOncePerRequest", Boolean.TRUE); + } // SEC-501 - should paths stored in request maps be converted to lower case // true if Ant path and using lower case 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 ba574adb9f..846d3514c1 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 @@ -214,6 +214,9 @@ http.attlist &= http.attlist &= ## Allows a customized AuthenticationEntryPoint to be used. attribute entry-point-ref {xsd:string}? +http.attlist &= + ## Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "false" + attribute once-per-request {"true" | "false"}? intercept-url = 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 b2ad905700..457e1f1fe4 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 @@ -710,6 +710,18 @@ used. + + + Corresponds to the observeOncePerRequest property of + FilterSecurityInterceptor. Defaults to "false" + + + + + + + + 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 99119f979c..63aae7bc47 100644 --- a/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java +++ b/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java @@ -189,6 +189,17 @@ public class HttpSecurityBeanDefinitionParserTests { setContext("" + AUTH_PROVIDER_XML); } + @Test + public void oncePerRequestAttributeIsSupported() { + setContext("" + AUTH_PROVIDER_XML); + FilterChainProxy filterChainProxy = getFilterChainProxy(); + List filters = filterChainProxy.getFilters("/someurl"); + + FilterSecurityInterceptor fsi = (FilterSecurityInterceptor) filters.get(filters.size() - 1); + + assertTrue(fsi.isObserveOncePerRequest()); + } + @Test public void interceptUrlWithRequiresChannelAddsChannelFilterToStack() { setContext( @@ -196,7 +207,6 @@ public class HttpSecurityBeanDefinitionParserTests { " " + " " + AUTH_PROVIDER_XML); FilterChainProxy filterChainProxy = getFilterChainProxy(); - List filters = filterChainProxy.getFilters("/someurl"); assertEquals("Expected 12 filters in chain", 12, filters.size());