Ver Fonte

OPEN - issue SEC-953: Query string isn't ignored while url - filterchain pattern matching
http://jira.springframework.org/browse/SEC-953. Added stripQueryStringFromUrls parameter to FilterChainProxy which works the same as the one on DefaultFilterInvocationDefinitionSource. This defaults to true when used with ant path matching.

Luke Taylor há 17 anos atrás
pai
commit
39a656eb78

+ 121 - 120
core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java

@@ -50,16 +50,16 @@ import org.w3c.dom.Element;
  * @version $Id$
  * @version $Id$
  */
  */
 public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
-	static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class);
+    static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class);
 
 
     static final String ATT_REALM = "realm";
     static final String ATT_REALM = "realm";
     static final String DEF_REALM = "Spring Security Application";
     static final String DEF_REALM = "Spring Security Application";
 
 
     static final String ATT_PATH_PATTERN = "pattern";
     static final String ATT_PATH_PATTERN = "pattern";
-    
+
     static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection";
     static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection";
     static final String OPT_SESSION_FIXATION_NO_PROTECTION = "none";
     static final String OPT_SESSION_FIXATION_NO_PROTECTION = "none";
-    static final String OPT_SESSION_FIXATION_CLEAN_SESSION = "newSession";    
+    static final String OPT_SESSION_FIXATION_CLEAN_SESSION = "newSession";
     static final String OPT_SESSION_FIXATION_MIGRATE_SESSION = "migrateSession";
     static final String OPT_SESSION_FIXATION_MIGRATE_SESSION = "migrateSession";
 
 
     static final String ATT_PATH_TYPE = "path-type";
     static final String ATT_PATH_TYPE = "path-type";
@@ -91,9 +91,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
     static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
     static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
     static final String DEF_SERVLET_API_PROVISION = "true";
     static final String DEF_SERVLET_API_PROVISION = "true";
 
 
-    static final String ATT_ACCESS_MGR = "access-decision-manager-ref";    
+    static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
     static final String ATT_USER_SERVICE_REF = "user-service-ref";
     static final String ATT_USER_SERVICE_REF = "user-service-ref";
-    
+
     static final String ATT_ENTRY_POINT_REF = "entry-point-ref";
     static final String ATT_ENTRY_POINT_REF = "entry-point-ref";
     static final String ATT_ONCE_PER_REQUEST = "once-per-request";
     static final String ATT_ONCE_PER_REQUEST = "once-per-request";
     static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page";
     static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page";
@@ -106,20 +106,20 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         // SEC-501 - should paths stored in request maps be converted to lower case
         // SEC-501 - should paths stored in request maps be converted to lower case
         // true if Ant path and using lower case
         // true if Ant path and using lower case
         final boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
         final boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
-        
+
         final List interceptUrlElts = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
         final List interceptUrlElts = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
         final Map filterChainMap =  new LinkedHashMap();
         final Map filterChainMap =  new LinkedHashMap();
         final LinkedHashMap channelRequestMap = new LinkedHashMap();
         final LinkedHashMap channelRequestMap = new LinkedHashMap();
 
 
         registerFilterChainProxy(parserContext, filterChainMap, matcher, source);
         registerFilterChainProxy(parserContext, filterChainMap, matcher, source);
-        
-        parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap, 
+
+        parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
                 convertPathsToLowerCase, parserContext);
                 convertPathsToLowerCase, parserContext);
 
 
         boolean allowSessionCreation = registerHttpSessionIntegrationFilter(element, parserContext);
         boolean allowSessionCreation = registerHttpSessionIntegrationFilter(element, parserContext);
-        
+
         registerServletApiFilter(element, parserContext);
         registerServletApiFilter(element, parserContext);
-                
+
         // Set up the access manager reference for http
         // Set up the access manager reference for http
         String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
         String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
 
 
@@ -127,7 +127,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
             ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
             accessManagerId = BeanIds.ACCESS_MANAGER;
             accessManagerId = BeanIds.ACCESS_MANAGER;
         }
         }
-        
+
         // Register the portMapper. A default will always be created, even if no element exists.
         // Register the portMapper. A default will always be created, even if no element exists.
         BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse(
         BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse(
                 DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), parserContext);
                 DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), parserContext);
@@ -139,19 +139,19 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         if (channelRequestMap.size() > 0) {
         if (channelRequestMap.size() > 0) {
             // At least one channel requirement has been specified
             // At least one channel requirement has been specified
             registerChannelProcessingBeans(parserContext, matcher, channelRequestMap);
             registerChannelProcessingBeans(parserContext, matcher, channelRequestMap);
-        }        
-                
-        registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId, 
+        }
+
+        registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId,
                 parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, parserContext));
                 parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, parserContext));
 
 
         boolean sessionControlEnabled = registerConcurrentSessionControlBeansIfRequired(element, parserContext);
         boolean sessionControlEnabled = registerConcurrentSessionControlBeansIfRequired(element, parserContext);
-        
-        registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION), 
+
+        registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
                 sessionControlEnabled);
                 sessionControlEnabled);
 
 
         boolean autoConfig = false;
         boolean autoConfig = false;
         if ("true".equals(element.getAttribute(ATT_AUTO_CONFIG))) {
         if ("true".equals(element.getAttribute(ATT_AUTO_CONFIG))) {
-        	autoConfig = true;
+            autoConfig = true;
         }
         }
 
 
         Element anonymousElt = DomUtils.getChildElementByTagName(element, Elements.ANONYMOUS);
         Element anonymousElt = DomUtils.getChildElementByTagName(element, Elements.ANONYMOUS);
@@ -160,7 +160,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         }
         }
 
 
         parseRememberMeAndLogout(element, autoConfig, parserContext);
         parseRememberMeAndLogout(element, autoConfig, parserContext);
-        
+
         parseBasicFormLoginAndOpenID(element, parserContext, autoConfig, allowSessionCreation);
         parseBasicFormLoginAndOpenID(element, parserContext, autoConfig, allowSessionCreation);
 
 
         Element x509Elt = DomUtils.getChildElementByTagName(element, Elements.X509);
         Element x509Elt = DomUtils.getChildElementByTagName(element, Elements.X509);
@@ -175,48 +175,49 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         RootBeanDefinition postProcessor2 = new RootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
         RootBeanDefinition postProcessor2 = new RootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
         postProcessor2.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         postProcessor2.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         registry.registerBeanDefinition(BeanIds.USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR, postProcessor2);
         registry.registerBeanDefinition(BeanIds.USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR, postProcessor2);
-        
+
         return null;
         return null;
     }
     }
-    
+
     private void parseRememberMeAndLogout(Element elt, boolean autoConfig, ParserContext pc) {
     private void parseRememberMeAndLogout(Element elt, boolean autoConfig, ParserContext pc) {
         // Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
         // Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
         Element rememberMeElt = DomUtils.getChildElementByTagName(elt, Elements.REMEMBER_ME);
         Element rememberMeElt = DomUtils.getChildElementByTagName(elt, Elements.REMEMBER_ME);
         String rememberMeServices = null;
         String rememberMeServices = null;
-        
+
         if (rememberMeElt != null || autoConfig) {
         if (rememberMeElt != null || autoConfig) {
-        	RememberMeBeanDefinitionParser rmbdp = new RememberMeBeanDefinitionParser();
-        	rmbdp.parse(rememberMeElt, pc);
-        	rememberMeServices = rmbdp.getServicesName();
+            RememberMeBeanDefinitionParser rmbdp = new RememberMeBeanDefinitionParser();
+            rmbdp.parse(rememberMeElt, pc);
+            rememberMeServices = rmbdp.getServicesName();
             // Post processor to inject RememberMeServices into filters which need it
             // Post processor to inject RememberMeServices into filters which need it
             RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
             RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
             rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
             rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-            pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor);            
+            pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor);
         }
         }
-        
+
         Element logoutElt = DomUtils.getChildElementByTagName(elt, Elements.LOGOUT);
         Element logoutElt = DomUtils.getChildElementByTagName(elt, Elements.LOGOUT);
         if (logoutElt != null || autoConfig) {
         if (logoutElt != null || autoConfig) {
             new LogoutBeanDefinitionParser(rememberMeServices).parse(logoutElt, pc);
             new LogoutBeanDefinitionParser(rememberMeServices).parse(logoutElt, pc);
-        }    	
+        }
     }
     }
-    
+
     private void registerFilterChainProxy(ParserContext pc, Map filterChainMap, UrlMatcher matcher, Object source) {
     private void registerFilterChainProxy(ParserContext pc, Map filterChainMap, UrlMatcher matcher, Object source) {
         if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
         if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
             pc.getReaderContext().error("Duplicate <http> element detected", source);
             pc.getReaderContext().error("Duplicate <http> element detected", source);
         }
         }
-        
+
         RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
         RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
         filterChainProxy.setSource(source);
         filterChainProxy.setSource(source);
         filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher);
         filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher);
+        filterChainProxy.getPropertyValues().addPropertyValue("stripQueryStringFromUrls", matcher instanceof AntUrlPathMatcher);
         filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
         filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
         pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
         pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
-        pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);        
+        pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
     }
     }
 
 
     private boolean registerHttpSessionIntegrationFilter(Element element, ParserContext pc) {
     private boolean registerHttpSessionIntegrationFilter(Element element, ParserContext pc) {
         RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
         RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
         boolean sessionCreationAllowed = true;
         boolean sessionCreationAllowed = true;
-        
+
         String createSession = element.getAttribute(ATT_CREATE_SESSION);
         String createSession = element.getAttribute(ATT_CREATE_SESSION);
         if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) {
         if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) {
             httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
             httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
@@ -233,11 +234,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
 
 
         pc.getRegistry().registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif);
         pc.getRegistry().registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif);
         ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER));
         ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER));
-        
+
         return sessionCreationAllowed;
         return sessionCreationAllowed;
     }
     }
 
 
-    // Adds the servlet-api integration filter if required    
+    // Adds the servlet-api integration filter if required
     private void registerServletApiFilter(Element element, ParserContext pc) {
     private void registerServletApiFilter(Element element, ParserContext pc) {
         String provideServletApi = element.getAttribute(ATT_SERVLET_API_PROVISION);
         String provideServletApi = element.getAttribute(ATT_SERVLET_API_PROVISION);
         if (!StringUtils.hasText(provideServletApi)) {
         if (!StringUtils.hasText(provideServletApi)) {
@@ -250,27 +251,27 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER));
             ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER));
         }
         }
     }
     }
-    
+
     private boolean registerConcurrentSessionControlBeansIfRequired(Element element, ParserContext parserContext) {
     private boolean registerConcurrentSessionControlBeansIfRequired(Element element, ParserContext parserContext) {
         Element sessionControlElt = DomUtils.getChildElementByTagName(element, Elements.CONCURRENT_SESSIONS);
         Element sessionControlElt = DomUtils.getChildElementByTagName(element, Elements.CONCURRENT_SESSIONS);
         if (sessionControlElt == null) {
         if (sessionControlElt == null) {
             return false;
             return false;
         }
         }
-        
+
         new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext);
         new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext);
         logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true");
         logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true");
-        BeanDefinition sessionIntegrationFilter = parserContext.getRegistry().getBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER); 
+        BeanDefinition sessionIntegrationFilter = parserContext.getRegistry().getBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER);
         sessionIntegrationFilter.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
         sessionIntegrationFilter.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
         return true;
         return true;
     }
     }
-    
+
     private void registerExceptionTranslationFilter(Element element, ParserContext pc, boolean allowSessionCreation) {
     private void registerExceptionTranslationFilter(Element element, ParserContext pc, boolean allowSessionCreation) {
-    	String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
-    	ConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element));
+        String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
+        ConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element));
         BeanDefinitionBuilder exceptionTranslationFilterBuilder
         BeanDefinitionBuilder exceptionTranslationFilterBuilder
             = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
             = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
         exceptionTranslationFilterBuilder.addPropertyValue("createSessionAllowed", new Boolean(allowSessionCreation));
         exceptionTranslationFilterBuilder.addPropertyValue("createSessionAllowed", new Boolean(allowSessionCreation));
-        
+
         if (StringUtils.hasText(accessDeniedPage)) {
         if (StringUtils.hasText(accessDeniedPage)) {
             AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
             AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
             accessDeniedHandler.setErrorPage(accessDeniedPage);
             accessDeniedHandler.setErrorPage(accessDeniedPage);
@@ -280,27 +281,27 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         pc.getRegistry().registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition());
         pc.getRegistry().registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition());
         ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.EXCEPTION_TRANSLATION_FILTER));
         ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.EXCEPTION_TRANSLATION_FILTER));
     }
     }
-    
+
     private void registerFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher,
     private void registerFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher,
             String accessManagerId, LinkedHashMap filterInvocationDefinitionMap) {
             String accessManagerId, LinkedHashMap filterInvocationDefinitionMap) {
         BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
         BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
 
 
         builder.addPropertyReference("accessDecisionManager", accessManagerId);
         builder.addPropertyReference("accessDecisionManager", accessManagerId);
         builder.addPropertyReference("authenticationManager", BeanIds.AUTHENTICATION_MANAGER);
         builder.addPropertyReference("authenticationManager", BeanIds.AUTHENTICATION_MANAGER);
-        
+
         if ("false".equals(element.getAttribute(ATT_ONCE_PER_REQUEST))) {
         if ("false".equals(element.getAttribute(ATT_ONCE_PER_REQUEST))) {
             builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE);
             builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE);
         }
         }
-        
-        DefaultFilterInvocationDefinitionSource fids = 
+
+        DefaultFilterInvocationDefinitionSource fids =
             new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap);
             new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap);
         fids.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
         fids.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
-        
+
         builder.addPropertyValue("objectDefinitionSource", fids);
         builder.addPropertyValue("objectDefinitionSource", fids);
         pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition());
         pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition());
         ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR));
         ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR));
     }
     }
-    
+
     private void registerChannelProcessingBeans(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) {
     private void registerChannelProcessingBeans(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) {
         RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
         RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
         channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager",
         channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager",
@@ -308,7 +309,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
         DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
             new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap);
             new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap);
         channelFilterInvDefSource.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
         channelFilterInvDefSource.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
-        
+
         channelFilter.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource",
         channelFilter.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource",
                 channelFilterInvDefSource);
                 channelFilterInvDefSource);
         RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
         RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
@@ -329,161 +330,161 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter);
         pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter);
         ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.CHANNEL_PROCESSING_FILTER));
         ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.CHANNEL_PROCESSING_FILTER));
         pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager);
         pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager);
-        
+
     }
     }
-    
+
     private void registerSessionFixationProtectionFilter(ParserContext pc, String sessionFixationAttribute, boolean sessionControlEnabled) {
     private void registerSessionFixationProtectionFilter(ParserContext pc, String sessionFixationAttribute, boolean sessionControlEnabled) {
         if(!StringUtils.hasText(sessionFixationAttribute)) {
         if(!StringUtils.hasText(sessionFixationAttribute)) {
             sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION;
             sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION;
         }
         }
-        
+
         if (!sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION)) {
         if (!sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION)) {
-            BeanDefinitionBuilder sessionFixationFilter = 
+            BeanDefinitionBuilder sessionFixationFilter =
                 BeanDefinitionBuilder.rootBeanDefinition(SessionFixationProtectionFilter.class);
                 BeanDefinitionBuilder.rootBeanDefinition(SessionFixationProtectionFilter.class);
-            sessionFixationFilter.addPropertyValue("migrateSessionAttributes", 
+            sessionFixationFilter.addPropertyValue("migrateSessionAttributes",
                     Boolean.valueOf(sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)));
                     Boolean.valueOf(sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)));
             if (sessionControlEnabled) {
             if (sessionControlEnabled) {
                 sessionFixationFilter.addPropertyReference("sessionRegistry", BeanIds.SESSION_REGISTRY);
                 sessionFixationFilter.addPropertyReference("sessionRegistry", BeanIds.SESSION_REGISTRY);
             }
             }
-            pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER, 
+            pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER,
                     sessionFixationFilter.getBeanDefinition());
                     sessionFixationFilter.getBeanDefinition());
             ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
             ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
         }
         }
     }
     }
-    
+
     private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation) {
     private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation) {
         RootBeanDefinition formLoginFilter = null;
         RootBeanDefinition formLoginFilter = null;
         RootBeanDefinition formLoginEntryPoint = null;
         RootBeanDefinition formLoginEntryPoint = null;
-        String formLoginPage = null;        
+        String formLoginPage = null;
         RootBeanDefinition openIDFilter = null;
         RootBeanDefinition openIDFilter = null;
         RootBeanDefinition openIDEntryPoint = null;
         RootBeanDefinition openIDEntryPoint = null;
         String openIDLoginPage = null;
         String openIDLoginPage = null;
-    	
+
         String realm = element.getAttribute(ATT_REALM);
         String realm = element.getAttribute(ATT_REALM);
         if (!StringUtils.hasText(realm)) {
         if (!StringUtils.hasText(realm)) {
-        	realm = DEF_REALM;
+            realm = DEF_REALM;
         }
         }
-        
+
         Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
         Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
         if (basicAuthElt != null || autoConfig) {
         if (basicAuthElt != null || autoConfig) {
             new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc);
             new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc);
         }
         }
-        
-    	Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
-        
+
+        Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
+
         if (formLoginElt != null || autoConfig) {
         if (formLoginElt != null || autoConfig) {
-        	FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check", 
-        			"org.springframework.security.ui.webapp.AuthenticationProcessingFilter");
-        	
+            FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
+                    "org.springframework.security.ui.webapp.AuthenticationProcessingFilter");
+
             parser.parse(formLoginElt, pc);
             parser.parse(formLoginElt, pc);
             formLoginFilter = parser.getFilterBean();
             formLoginFilter = parser.getFilterBean();
             formLoginEntryPoint = parser.getEntryPointBean();
             formLoginEntryPoint = parser.getEntryPointBean();
             formLoginPage = parser.getLoginPage();
             formLoginPage = parser.getLoginPage();
         }
         }
-        
+
         Element openIDLoginElt = DomUtils.getChildElementByTagName(element, Elements.OPENID_LOGIN);
         Element openIDLoginElt = DomUtils.getChildElementByTagName(element, Elements.OPENID_LOGIN);
 
 
         if (openIDLoginElt != null) {
         if (openIDLoginElt != null) {
-        	FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check", 
-        			"org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter");
-        	
+            FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
+                    "org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter");
+
             parser.parse(openIDLoginElt, pc);
             parser.parse(openIDLoginElt, pc);
             openIDFilter = parser.getFilterBean();
             openIDFilter = parser.getFilterBean();
             openIDEntryPoint = parser.getEntryPointBean();
             openIDEntryPoint = parser.getEntryPointBean();
             openIDLoginPage = parser.getLoginPage();
             openIDLoginPage = parser.getLoginPage();
-            
-            BeanDefinitionBuilder openIDProviderBuilder = 
+
+            BeanDefinitionBuilder openIDProviderBuilder =
                 BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.providers.openid.OpenIDAuthenticationProvider");
                 BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.providers.openid.OpenIDAuthenticationProvider");
-            
+
             String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
             String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
-            
+
             if (StringUtils.hasText(userService)) {
             if (StringUtils.hasText(userService)) {
                 openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
                 openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
             }
             }
-            
+
             BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
             BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
             pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider);
             pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider);
             ConfigUtils.addAuthenticationProvider(pc, BeanIds.OPEN_ID_PROVIDER);
             ConfigUtils.addAuthenticationProvider(pc, BeanIds.OPEN_ID_PROVIDER);
         }
         }
-        
+
         boolean needLoginPage = false;
         boolean needLoginPage = false;
-        
+
         if (formLoginFilter != null) {
         if (formLoginFilter != null) {
-        	needLoginPage = true;
-        	formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
-	        pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter);
-	        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
-	        pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint);
-        }        
+            needLoginPage = true;
+            formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
+            pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter);
+            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
+            pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint);
+        }
 
 
         if (openIDFilter != null) {
         if (openIDFilter != null) {
-        	needLoginPage = true;
-        	openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
-	        pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter);
-	        ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
-	        pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint);
+            needLoginPage = true;
+            openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
+            pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter);
+            ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
+            pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint);
         }
         }
 
 
         // If no login page has been defined, add in the default page generator.
         // If no login page has been defined, add in the default page generator.
         if (needLoginPage && formLoginPage == null && openIDLoginPage == null) {
         if (needLoginPage && formLoginPage == null && openIDLoginPage == null) {
             logger.info("No login page configured. The default internal one will be used. Use the '"
             logger.info("No login page configured. The default internal one will be used. Use the '"
                      + FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page.");
                      + FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page.");
-            BeanDefinitionBuilder loginPageFilter = 
-            	BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
-            
+            BeanDefinitionBuilder loginPageFilter =
+                BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
+
             if (formLoginFilter != null) {
             if (formLoginFilter != null) {
-            	loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
+                loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
             }
             }
-            
+
             if (openIDFilter != null) {
             if (openIDFilter != null) {
-            	loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
+                loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
             }
             }
 
 
-            pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER, 
-            		loginPageFilter.getBeanDefinition());
+            pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER,
+                    loginPageFilter.getBeanDefinition());
             ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER));
             ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER));
         }
         }
-        
+
         // We need to establish the main entry point.
         // We need to establish the main entry point.
         // First check if a custom entry point bean is set
         // First check if a custom entry point bean is set
         String customEntryPoint = element.getAttribute(ATT_ENTRY_POINT_REF);
         String customEntryPoint = element.getAttribute(ATT_ENTRY_POINT_REF);
-        
+
         if (StringUtils.hasText(customEntryPoint)) {
         if (StringUtils.hasText(customEntryPoint)) {
             pc.getRegistry().registerAlias(customEntryPoint, BeanIds.MAIN_ENTRY_POINT);
             pc.getRegistry().registerAlias(customEntryPoint, BeanIds.MAIN_ENTRY_POINT);
             return;
             return;
         }
         }
-        
+
         // Basic takes precedence if explicit element is used and no others are configured
         // Basic takes precedence if explicit element is used and no others are configured
         if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null) {
         if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null) {
-        	pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
-        	return;
+            pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
+            return;
         }
         }
-        
+
         // If formLogin has been enabled either through an element or auto-config, then it is used if no openID login page
         // If formLogin has been enabled either through an element or auto-config, then it is used if no openID login page
         // has been set
         // has been set
         if (formLoginFilter != null && openIDLoginPage == null) {
         if (formLoginFilter != null && openIDLoginPage == null) {
-        	pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
-        	return;        	
+            pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
+            return;
         }
         }
-        
+
         // Otherwise use OpenID if enabled
         // Otherwise use OpenID if enabled
         if (openIDFilter != null && formLoginFilter == null) {
         if (openIDFilter != null && formLoginFilter == null) {
-        	pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
-        	return;        	
+            pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
+            return;
         }
         }
-        
+
         // If X.509 has been enabled, use the preauth entry point.
         // If X.509 has been enabled, use the preauth entry point.
         if (DomUtils.getChildElementByTagName(element, Elements.X509) != null) {
         if (DomUtils.getChildElementByTagName(element, Elements.X509) != null) {
             pc.getRegistry().registerAlias(BeanIds.PRE_AUTH_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
             pc.getRegistry().registerAlias(BeanIds.PRE_AUTH_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
             return;
             return;
         }
         }
-        
+
         pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " +
         pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " +
-        		"make sure you have a login mechanism configured through the namespace (such as form-login) or " +
-        		"specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attribute ", 
+                "make sure you have a login mechanism configured through the namespace (such as form-login) or " +
+                "specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attribute ",
                 pc.extractSource(element));
                 pc.extractSource(element));
     }
     }
-    
+
     static UrlMatcher createUrlMatcher(Element element) {
     static UrlMatcher createUrlMatcher(Element element) {
         String patternType = element.getAttribute(ATT_PATH_TYPE);
         String patternType = element.getAttribute(ATT_PATH_TYPE);
         if (!StringUtils.hasText(patternType)) {
         if (!StringUtils.hasText(patternType)) {
@@ -517,8 +518,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             }
             }
             // Default for regex is no change
             // Default for regex is no change
         }
         }
-        
-        return matcher;        
+
+        return matcher;
     }
     }
 
 
     /**
     /**
@@ -562,7 +563,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
                 editor.setAsText(channelConfigAttribute);
                 editor.setAsText(channelConfigAttribute);
                 channelRequestMap.put(new RequestKey(path), (ConfigAttributeDefinition) editor.getValue());
                 channelRequestMap.put(new RequestKey(path), (ConfigAttributeDefinition) editor.getValue());
             }
             }
-            
+
             String filters = urlElt.getAttribute(ATT_FILTERS);
             String filters = urlElt.getAttribute(ATT_FILTERS);
 
 
             if (StringUtils.hasText(filters)) {
             if (StringUtils.hasText(filters)) {
@@ -575,10 +576,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             }
             }
         }
         }
     }
     }
-    
+
     static LinkedHashMap parseInterceptUrlsForFilterInvocationRequestMap(List urlElts,  boolean useLowerCasePaths, ParserContext parserContext) {
     static LinkedHashMap parseInterceptUrlsForFilterInvocationRequestMap(List urlElts,  boolean useLowerCasePaths, ParserContext parserContext) {
         LinkedHashMap filterInvocationDefinitionMap = new LinkedHashMap();
         LinkedHashMap filterInvocationDefinitionMap = new LinkedHashMap();
-        
+
         Iterator urlEltsIterator = urlElts.iterator();
         Iterator urlEltsIterator = urlElts.iterator();
         ConfigAttributeEditor editor = new ConfigAttributeEditor();
         ConfigAttributeEditor editor = new ConfigAttributeEditor();
 
 
@@ -606,16 +607,16 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
             if (StringUtils.hasText(access)) {
             if (StringUtils.hasText(access)) {
                 editor.setAsText(access);
                 editor.setAsText(access);
                 Object key = new RequestKey(path, method);
                 Object key = new RequestKey(path, method);
-                
+
                 if (filterInvocationDefinitionMap.containsKey(key)) {
                 if (filterInvocationDefinitionMap.containsKey(key)) {
-                	logger.warn("Duplicate URL defined: " + key + ". The original attribute values will be overwritten");
+                    logger.warn("Duplicate URL defined: " + key + ". The original attribute values will be overwritten");
                 }
                 }
-                
+
                 filterInvocationDefinitionMap.put(key, editor.getValue());
                 filterInvocationDefinitionMap.put(key, editor.getValue());
             }
             }
         }
         }
-        
+
         return filterInvocationDefinitionMap;
         return filterInvocationDefinitionMap;
     }
     }
-    
+
 }
 }

+ 21 - 2
core/src/main/java/org/springframework/security/util/FilterChainProxy.java

@@ -107,6 +107,7 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
     /** Compiled pattern version of the filter chain map */
     /** Compiled pattern version of the filter chain map */
     private Map filterChainMap;
     private Map filterChainMap;
     private UrlMatcher matcher = new AntUrlPathMatcher();
     private UrlMatcher matcher = new AntUrlPathMatcher();
+    private boolean stripQueryStringFromUrls = true;
     private DefaultFilterInvocationDefinitionSource fids;
     private DefaultFilterInvocationDefinitionSource fids;
 
 
     //~ Methods ========================================================================================================
     //~ Methods ========================================================================================================
@@ -116,8 +117,8 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
         if (fids != null) {
         if (fids != null) {
             Assert.isNull(uncompiledFilterChainMap, "Set the filterChainMap or FilterInvocationDefinitionSource but not both");
             Assert.isNull(uncompiledFilterChainMap, "Set the filterChainMap or FilterInvocationDefinitionSource but not both");
             FIDSToFilterChainMapConverter converter = new FIDSToFilterChainMapConverter(fids, applicationContext);
             FIDSToFilterChainMapConverter converter = new FIDSToFilterChainMapConverter(fids, applicationContext);
-            setMatcher(converter.getMatcher());            
-            setFilterChainMap(converter.getFilterChainMap());            
+            setMatcher(converter.getMatcher());
+            setFilterChainMap(converter.getFilterChainMap());
             fids = null;
             fids = null;
         }
         }
 
 
@@ -181,6 +182,16 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
      * @return an ordered array of Filters defining the filter chain
      * @return an ordered array of Filters defining the filter chain
      */
      */
     public List getFilters(String url)  {
     public List getFilters(String url)  {
+        if (stripQueryStringFromUrls) {
+            // String query string - see SEC-953
+            int firstQuestionMarkIndex = url.indexOf("?");
+
+            if (firstQuestionMarkIndex != -1) {
+                url = url.substring(0, firstQuestionMarkIndex);
+            }
+        }
+
+
         Iterator filterChains = filterChainMap.entrySet().iterator();
         Iterator filterChains = filterChainMap.entrySet().iterator();
 
 
         while (filterChains.hasNext()) {
         while (filterChains.hasNext()) {
@@ -319,6 +330,14 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
         return matcher;
         return matcher;
     }
     }
 
 
+    /**
+     * If set to 'true', the query string will be stripped from the request URL before
+     * attempting to find a matching filter chain. This is the default value.
+     */
+    public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) {
+        this.stripQueryStringFromUrls = stripQueryStringFromUrls;
+    }
+
     public String toString() {
     public String toString() {
         StringBuffer sb = new StringBuffer();
         StringBuffer sb = new StringBuffer();
         sb.append("FilterChainProxy[");
         sb.append("FilterChainProxy[");

+ 3 - 1
core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java

@@ -79,6 +79,8 @@ public class HttpSecurityBeanDefinitionParserTests {
         List filterList = getFilters("/anyurl");
         List filterList = getFilters("/anyurl");
 
 
         checkAutoConfigFilters(filterList);
         checkAutoConfigFilters(filterList);
+
+        assertEquals(true, FieldUtils.getFieldValue(appContext.getBean("_filterChainProxy"), "stripQueryStringFromUrls"));
         assertEquals(true, FieldUtils.getFieldValue(filterList.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
         assertEquals(true, FieldUtils.getFieldValue(filterList.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
     }
     }
 
 
@@ -136,6 +138,7 @@ public class HttpSecurityBeanDefinitionParserTests {
         // This will be matched by the default pattern ".*"
         // This will be matched by the default pattern ".*"
         List allFilters = getFilters("/ImCaughtByTheUniversalMatchPattern");
         List allFilters = getFilters("/ImCaughtByTheUniversalMatchPattern");
         checkAutoConfigFilters(allFilters);
         checkAutoConfigFilters(allFilters);
+        assertEquals(false, FieldUtils.getFieldValue(appContext.getBean("_filterChainProxy"), "stripQueryStringFromUrls"));
         assertEquals(false, FieldUtils.getFieldValue(allFilters.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
         assertEquals(false, FieldUtils.getFieldValue(allFilters.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
     }
     }
 
 
@@ -149,7 +152,6 @@ public class HttpSecurityBeanDefinitionParserTests {
         // These will be matched by the default pattern "/**"
         // These will be matched by the default pattern "/**"
         checkAutoConfigFilters(getFilters("/secure"));
         checkAutoConfigFilters(getFilters("/secure"));
         checkAutoConfigFilters(getFilters("/ImCaughtByTheUniversalMatchPattern"));
         checkAutoConfigFilters(getFilters("/ImCaughtByTheUniversalMatchPattern"));
-
     }
     }
 
 
     @Test
     @Test

+ 27 - 17
core/src/test/java/org/springframework/security/util/FilterChainProxyTests.java

@@ -62,20 +62,16 @@ public class FilterChainProxyTests {
         }
         }
     }
     }
 
 
-    @Test
+    @Test(expected=IllegalArgumentException.class)
     public void testDetectsFilterInvocationDefinitionSourceThatDoesNotReturnAllConfigAttributes() throws Exception {
     public void testDetectsFilterInvocationDefinitionSourceThatDoesNotReturnAllConfigAttributes() throws Exception {
         FilterChainProxy filterChainProxy = new FilterChainProxy();
         FilterChainProxy filterChainProxy = new FilterChainProxy();
         filterChainProxy.setApplicationContext(new StaticApplicationContext());
         filterChainProxy.setApplicationContext(new StaticApplicationContext());
 
 
-        try {
-            filterChainProxy.setFilterInvocationDefinitionSource(new MockFilterInvocationDefinitionSource(false, false));
-            filterChainProxy.afterPropertiesSet();
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-        }
+        filterChainProxy.setFilterInvocationDefinitionSource(new MockFilterInvocationDefinitionSource(false, false));
+        filterChainProxy.afterPropertiesSet();
     }
     }
 
 
-    @Test
+    @Test(expected=IllegalArgumentException.class)
     public void testDetectsIfConfigAttributeDoesNotReturnValueForGetAttributeMethod() throws Exception {
     public void testDetectsIfConfigAttributeDoesNotReturnValueForGetAttributeMethod() throws Exception {
         FilterChainProxy filterChainProxy = new FilterChainProxy();
         FilterChainProxy filterChainProxy = new FilterChainProxy();
         filterChainProxy.setApplicationContext(new StaticApplicationContext());
         filterChainProxy.setApplicationContext(new StaticApplicationContext());
@@ -89,12 +85,8 @@ public class FilterChainProxyTests {
 
 
         filterChainProxy.setFilterInvocationDefinitionSource(fids);
         filterChainProxy.setFilterInvocationDefinitionSource(fids);
 
 
-        try {
-            filterChainProxy.afterPropertiesSet();
-            filterChainProxy.init(new MockFilterConfig());
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-        }
+        filterChainProxy.afterPropertiesSet();
+        filterChainProxy.init(new MockFilterConfig());
     }
     }
 
 
     @Test(expected = IllegalArgumentException.class)
     @Test(expected = IllegalArgumentException.class)
@@ -131,18 +123,18 @@ public class FilterChainProxyTests {
         }
         }
     }
     }
 
 
-    @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);
         doNormalOperation(filterChainProxy);
         doNormalOperation(filterChainProxy);
     }
     }
 
 
-    @Test    
+    @Test
     public void proxyPathWithoutLowerCaseConversionShouldntMatchDifferentCasePath() throws Exception {
     public void proxyPathWithoutLowerCaseConversionShouldntMatchDifferentCasePath() throws Exception {
         FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChainNonLowerCase", FilterChainProxy.class);
         FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChainNonLowerCase", FilterChainProxy.class);
         assertNull(filterChainProxy.getFilters("/some/other/path/blah"));
         assertNull(filterChainProxy.getFilters("/some/other/path/blah"));
     }
     }
-    
+
     @Test
     @Test
     public void normalOperationWithNewConfig() throws Exception {
     public void normalOperationWithNewConfig() throws Exception {
         FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxy", FilterChainProxy.class);
         FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxy", FilterChainProxy.class);
@@ -164,6 +156,24 @@ public class FilterChainProxyTests {
         doNormalOperation(filterChainProxy);
         doNormalOperation(filterChainProxy);
     }
     }
 
 
+    @Test
+    public void pathWithNoMatchHasNoFilters() throws Exception {
+        FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxyNoDefaultPath", FilterChainProxy.class);
+        assertEquals(null, filterChainProxy.getFilters("/nomatch"));
+    }
+
+    @Test
+    public void urlStrippingPropertyIsRespected() throws Exception {
+        FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxyNoDefaultPath", FilterChainProxy.class);
+
+        // Should only match if we are stripping the query string
+        String url = "/blah.bar?x=something";
+        assertNotNull(filterChainProxy.getFilters(url));
+        assertEquals(2, filterChainProxy.getFilters(url).size());
+        filterChainProxy.setStripQueryStringFromUrls(false);
+        assertNull(filterChainProxy.getFilters(url));
+    }
+
     private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) throws Exception {
     private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) throws Exception {
         List filters = filterChainProxy.getFilters("/foo/blah");
         List filters = filterChainProxy.getFilters("/foo/blah");
         assertEquals(1, filters.size());
         assertEquals(1, filters.size());

+ 15 - 8
core/src/test/resources/org/springframework/security/util/filtertest-valid.xml

@@ -24,9 +24,9 @@
     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
 http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
 http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
 
 
-	<bean id="mockFilter" class="org.springframework.security.util.MockFilter"/>
+    <bean id="mockFilter" class="org.springframework.security.util.MockFilter"/>
 
 
-	<bean id="mockFilter2" class="org.springframework.security.util.MockFilter"/>
+    <bean id="mockFilter2" class="org.springframework.security.util.MockFilter"/>
 
 
     <!-- These are just here so we have filters of a specfic type to check the ordering is as expected -->
     <!-- These are just here so we have filters of a specfic type to check the ordering is as expected -->
     <bean id="sif" class="org.springframework.security.context.HttpSessionContextIntegrationFilter"/>
     <bean id="sif" class="org.springframework.security.context.HttpSessionContextIntegrationFilter"/>
@@ -41,11 +41,11 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
 
 
     <bean id="mockNotAFilter" class="org.springframework.security.util.MockNotAFilter"/>
     <bean id="mockNotAFilter" class="org.springframework.security.util.MockNotAFilter"/>
 
 
-	<bean id="filterChain" class="org.springframework.security.util.FilterChainProxy">
+    <bean id="filterChain" class="org.springframework.security.util.FilterChainProxy">
       <property name="filterInvocationDefinitionSource">
       <property name="filterInvocationDefinitionSource">
          <value>
          <value>
-		    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
-		    PATTERN_TYPE_APACHE_ANT
+            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
+            PATTERN_TYPE_APACHE_ANT
             /foo/**=mockFilter
             /foo/**=mockFilter
             /some/other/path/**=mockFilter
             /some/other/path/**=mockFilter
             /do/not/filter=#NONE#
             /do/not/filter=#NONE#
@@ -53,10 +53,10 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
       </property>
       </property>
     </bean>
     </bean>
 
 
-	<bean id="filterChainNonLowerCase" class="org.springframework.security.util.FilterChainProxy">
+    <bean id="filterChainNonLowerCase" class="org.springframework.security.util.FilterChainProxy">
       <property name="filterInvocationDefinitionSource">
       <property name="filterInvocationDefinitionSource">
          <value>
          <value>
-		    PATTERN_TYPE_APACHE_ANT
+            PATTERN_TYPE_APACHE_ANT
             /foo/**=mockFilter
             /foo/**=mockFilter
             /SOME/other/path/**=sif,mockFilter,mockFilter2
             /SOME/other/path/**=sif,mockFilter,mockFilter2
             /do/not/filter=#NONE#
             /do/not/filter=#NONE#
@@ -73,6 +73,13 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
         </sec:filter-chain-map>
         </sec:filter-chain-map>
     </bean>
     </bean>
 
 
+    <bean id="newFilterChainProxyNoDefaultPath" class="org.springframework.security.util.FilterChainProxy">
+        <sec:filter-chain-map path-type="ant">
+            <sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
+            <sec:filter-chain pattern="/*.bar" filters="mockFilter,mockFilter2"/>
+        </sec:filter-chain-map>
+    </bean>
+
     <bean id="newFilterChainProxyWrongPathOrder" class="org.springframework.security.util.FilterChainProxy">
     <bean id="newFilterChainProxyWrongPathOrder" class="org.springframework.security.util.FilterChainProxy">
         <sec:filter-chain-map path-type="ant">
         <sec:filter-chain-map path-type="ant">
             <sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
             <sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
@@ -117,7 +124,7 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
                       <ref local="apf"/>
                       <ref local="apf"/>
                       <ref local="mockFilter"/>
                       <ref local="mockFilter"/>
                     </list>
                     </list>
-                </entry>                
+                </entry>
             </map>
             </map>
         </property>
         </property>
     </bean>
     </bean>