Browse Source

Added checking of path ordering to FilterChainProxy to detect misplaced universal match ("/**").

Luke Taylor 18 years ago
parent
commit
55ef50a4df

+ 16 - 0
core/src/main/java/org/springframework/security/util/FilterChainProxy.java

@@ -117,6 +117,7 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
         }
         }
 
 
         Assert.notNull(uncompiledFilterChainMap, "filterChainMap must be set");
         Assert.notNull(uncompiledFilterChainMap, "filterChainMap must be set");
+
     }
     }
 
 
     public void init(FilterConfig filterConfig) throws ServletException {
     public void init(FilterConfig filterConfig) throws ServletException {
@@ -247,9 +248,24 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
      */
      */
     public void setFilterChainMap(Map filterChainMap) {
     public void setFilterChainMap(Map filterChainMap) {
         uncompiledFilterChainMap = new LinkedHashMap(filterChainMap);
         uncompiledFilterChainMap = new LinkedHashMap(filterChainMap);
+        checkPathOrder();
         createCompiledMap();
         createCompiledMap();
     }
     }
 
 
+    private void checkPathOrder() {
+        // Check that the universal pattern is listed at the end, if at all
+        String[] paths = (String[]) uncompiledFilterChainMap.keySet().toArray(new String[0]);
+        String universalMatch = matcher.getUniversalMatchPattern();
+
+        for (int i=0; i < paths.length-1; i++) {
+            if (paths[i].equals(universalMatch)) {
+                throw new IllegalArgumentException("A universal match pattern " + universalMatch + " is defined " +
+                        " before other patterns in the filter chain, causing them to be ignored. Please check the " +
+                        "ordering in your <security:http> namespace or FilterChainProxy bean configuration");
+            }
+        }
+    }
+
     private void createCompiledMap() {
     private void createCompiledMap() {
         Iterator paths = uncompiledFilterChainMap.keySet().iterator();
         Iterator paths = uncompiledFilterChainMap.keySet().iterator();
         filterChainMap = new LinkedHashMap(uncompiledFilterChainMap.size());
         filterChainMap = new LinkedHashMap(uncompiledFilterChainMap.size());

+ 14 - 5
core/src/test/java/org/springframework/security/util/FilterChainProxyTests.java

@@ -16,6 +16,11 @@
 package org.springframework.security.util;
 package org.springframework.security.util;
 
 
 
 
+import org.junit.After;
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.BeanCreationException;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 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;
@@ -28,11 +33,6 @@ import org.springframework.security.intercept.web.MockFilterInvocationDefinition
 import org.springframework.security.intercept.web.PathBasedFilterInvocationDefinitionMap;
 import org.springframework.security.intercept.web.PathBasedFilterInvocationDefinitionMap;
 import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
 import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
 
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import static org.junit.Assert.*;
-
 import java.util.List;
 import java.util.List;
 
 
 /**
 /**
@@ -126,6 +126,15 @@ public class FilterChainProxyTests {
         assertFalse(filter.isWasDestroyed());
         assertFalse(filter.isWasDestroyed());
     }
     }
 
 
+    @Test
+    public void misplacedUniversalPathShouldBeDetected() throws Exception {
+        try {
+            appCtx.getBean("newFilterChainProxyWrongPathOrder", FilterChainProxy.class);
+            fail("Expected BeanCreationException");
+        } catch (BeanCreationException expected) {
+        }
+    }
+
     @Test    
     @Test    
     public void normalOperation() throws Exception {
     public void normalOperation() throws Exception {
         FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChain", FilterChainProxy.class);
         FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChain", FilterChainProxy.class);

+ 9 - 1
core/src/test/resources/org/springframework/security/util/filtertest-valid.xml

@@ -18,7 +18,7 @@
  *
  *
  * $Id$
  * $Id$
 -->
 -->
-<beans 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: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-2.0.xsd
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
@@ -62,6 +62,14 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
         </sec:filter-chain-map>
         </sec:filter-chain-map>
     </bean>
     </bean>
 
 
+    <bean id="newFilterChainProxyWrongPathOrder" class="org.springframework.security.util.FilterChainProxy">
+        <sec:filter-chain-map pathType="ant">
+            <sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
+            <sec:filter-chain pattern="/**" filters="sif,apf,mockFilter"/>
+            <sec:filter-chain pattern="/some/other/path/**" filters="sif,mockFilter,mockFilter2"/>
+        </sec:filter-chain-map>
+    </bean>
+
     <bean id="newFilterChainProxyRegex" class="org.springframework.security.util.FilterChainProxy">
     <bean id="newFilterChainProxyRegex" class="org.springframework.security.util.FilterChainProxy">
         <sec:filter-chain-map pathType="regex">
         <sec:filter-chain-map pathType="regex">
             <sec:filter-chain pattern="\A/foo/.*\Z" filters="mockFilter"/>
             <sec:filter-chain pattern="\A/foo/.*\Z" filters="mockFilter"/>