浏览代码

SEC-1725: Add option to filter-chain to use an explicit request-matcher-ref instead of a "path" attribute.

Luke Taylor 14 年之前
父节点
当前提交
b5924db74d

+ 18 - 9
config/src/main/java/org/springframework/security/config/http/FilterChainBeanDefinitionParser.java

@@ -5,7 +5,10 @@ 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.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
 import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.util.Assert;
 import org.springframework.util.StringUtils;
 import org.w3c.dom.Element;
 
@@ -14,20 +17,24 @@ import java.util.*;
 /**
  * @author Luke Taylor
  */
-public class FilterChainBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
+public class FilterChainBeanDefinitionParser implements BeanDefinitionParser {
+    private static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref";
 
-    @Override
-    protected Class getBeanClass(Element element) {
-        return SecurityFilterChain.class;
-    }
-
-    @Override
-    protected void doParse(Element elt, BeanDefinitionBuilder builder) {
+    public BeanDefinition parse(Element elt, ParserContext pc) {
         MatcherType matcherType = MatcherType.fromElement(elt);
         String path = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN);
+        String requestMatcher = elt.getAttribute(ATT_REQUEST_MATCHER_REF);
         String filters = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS);
 
-        builder.addConstructorArgValue(matcherType.createMatcher(path, null));
+        BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(SecurityFilterChain.class);
+
+        if (StringUtils.hasText(path)) {
+            Assert.isTrue(!StringUtils.hasText(requestMatcher), "");
+            builder.addConstructorArgValue(matcherType.createMatcher(path, null));
+        } else {
+            Assert.isTrue(StringUtils.hasText(requestMatcher), "");
+            builder.addConstructorArgReference(requestMatcher);
+        }
 
         if (filters.equals(HttpSecurityBeanDefinitionParser.OPT_FILTERS_NONE)) {
             builder.addConstructorArgValue(Collections.EMPTY_LIST);
@@ -41,5 +48,7 @@ public class FilterChainBeanDefinitionParser extends AbstractSingleBeanDefinitio
 
             builder.addConstructorArgValue(filterChain);
         }
+
+        return builder.getBeanDefinition();
     }
 }

+ 1 - 1
config/src/main/resources/org/springframework/security/config/spring-security-3.1.rnc

@@ -446,7 +446,7 @@ filter-chain =
     ## 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}
 filter-chain.attlist &=
-    attribute pattern {xsd:token}
+    (attribute pattern {xsd:token} | attribute request-matcher-ref {xsd:token})
 filter-chain.attlist &=
     attribute filters {xsd:token}
 

+ 2 - 1
config/src/main/resources/org/springframework/security/config/spring-security-3.1.xsd

@@ -1006,7 +1006,8 @@
       <xs:attributeGroup ref="security:filter-chain.attlist"/>
     </xs:complexType></xs:element>
   <xs:attributeGroup name="filter-chain.attlist">
-    <xs:attribute name="pattern" use="required" type="xs:token"/>
+    <xs:attribute name="pattern" type="xs:token"/>
+    <xs:attribute name="request-matcher-ref" type="xs:token"/>
     <xs:attribute name="filters" use="required" type="xs:token"/>
   </xs:attributeGroup>
   <xs:element name="filter-security-metadata-source"><xs:annotation>

+ 6 - 6
config/src/test/resources/org/springframework/security/util/filtertest-valid.xml

@@ -47,10 +47,14 @@
 
     <bean id="mockNotAFilter" class="org.springframework.security.web.util.AnyRequestMatcher"/>
 
+    <bean id="fooMatcher" class="org.springframework.security.web.util.AntPathRequestMatcher">
+        <constructor-arg value="/foo/**"/>
+    </bean>
+
     <bean id="filterChain" class="org.springframework.security.web.FilterChainProxy">
         <constructor-arg>
            <util:list>
-               <sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
+               <sec:filter-chain request-matcher-ref="fooMatcher" filters="mockFilter"/>
                <sec:filter-chain pattern="/some/other/path/**" filters="mockFilter"/>
                <sec:filter-chain pattern="/do/not/filter" filters="none"/>
            </util:list>
@@ -121,11 +125,7 @@
         <constructor-arg>
             <list>
                 <bean class="org.springframework.security.web.SecurityFilterChain">
-                    <constructor-arg>
-                        <bean class="org.springframework.security.web.util.AntPathRequestMatcher">
-                            <constructor-arg value="/foo/**"/>
-                        </bean>
-                    </constructor-arg>
+                    <constructor-arg ref="fooMatcher"/>
                     <constructor-arg>
                         <list>
                           <ref local="mockFilter"/>