瀏覽代碼

Merge branch '6.1.x' into 6.2.x

Use CompositeFilterChainProxy
Rob Winch 1 年之前
父節點
當前提交
c7047add5d

+ 78 - 20
config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java

@@ -16,9 +16,14 @@
 
 package org.springframework.security.config.annotation.web.configuration;
 
+import java.io.IOException;
 import java.util.List;
 
 import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
 import jakarta.servlet.http.HttpServletRequest;
 
 import org.springframework.beans.BeanMetadataElement;
@@ -26,7 +31,6 @@ import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.FactoryBean;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
@@ -42,6 +46,8 @@ import org.springframework.security.web.FilterChainProxy;
 import org.springframework.security.web.SecurityFilterChain;
 import org.springframework.security.web.access.HandlerMappingIntrospectorRequestTransformer;
 import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
+import org.springframework.security.web.firewall.HttpFirewall;
+import org.springframework.security.web.firewall.RequestRejectedHandler;
 import org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver;
 import org.springframework.security.web.method.annotation.CsrfTokenArgumentResolver;
 import org.springframework.security.web.method.annotation.CurrentSecurityContextArgumentResolver;
@@ -135,11 +141,8 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
 				registry.registerBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + "RequestTransformer",
 						hmiRequestTransformer);
 
-				String filterChainProxyBeanName = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME
-						+ "Proxy";
 				BeanDefinition filterChainProxy = registry
 					.getBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
-				registry.registerBeanDefinition(filterChainProxyBeanName, filterChainProxy);
 
 				BeanDefinitionBuilder hmiCacheFilterBldr = BeanDefinitionBuilder
 					.rootBeanDefinition(HandlerMappingIntrospectorCachFilterFactoryBean.class)
@@ -147,9 +150,9 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
 
 				ManagedList<BeanMetadataElement> filters = new ManagedList<>();
 				filters.add(hmiCacheFilterBldr.getBeanDefinition());
-				filters.add(new RuntimeBeanReference(filterChainProxyBeanName));
+				filters.add(filterChainProxy);
 				BeanDefinitionBuilder compositeSpringSecurityFilterChainBldr = BeanDefinitionBuilder
-					.rootBeanDefinition(SpringSecurityFilterCompositeFilter.class)
+					.rootBeanDefinition(CompositeFilterChainProxy.class)
 					.addConstructorArgValue(filters);
 
 				registry.removeBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
@@ -188,21 +191,73 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
 	}
 
 	/**
-	 * Extension to {@link CompositeFilter} to expose private methods used by Spring
-	 * Security's test support
+	 * Extends {@link FilterChainProxy} to provide as much passivity as possible but
+	 * delegates to {@link CompositeFilter} for
+	 * {@link #doFilter(ServletRequest, ServletResponse, FilterChain)}.
 	 */
-	static class SpringSecurityFilterCompositeFilter extends CompositeFilter {
+	static class CompositeFilterChainProxy extends FilterChainProxy {
 
-		private FilterChainProxy springSecurityFilterChain;
+		/**
+		 * Used for {@link #doFilter(ServletRequest, ServletResponse, FilterChain)}
+		 */
+		private final Filter doFilterDelegate;
 
-		SpringSecurityFilterCompositeFilter(List<? extends Filter> filters) {
-			setFilters(filters); // for the parent
+		private final FilterChainProxy springSecurityFilterChain;
+
+		/**
+		 * Creates a new instance
+		 * @param filters the Filters to delegate to. One of which must be
+		 * FilterChainProxy.
+		 */
+		CompositeFilterChainProxy(List<? extends Filter> filters) {
+			this.doFilterDelegate = createDoFilterDelegate(filters);
+			this.springSecurityFilterChain = findFilterChainProxy(filters);
 		}
 
 		@Override
-		public void setFilters(List<? extends Filter> filters) {
-			super.setFilters(filters);
-			this.springSecurityFilterChain = findFilterChainProxy(filters);
+		public void afterPropertiesSet() {
+			this.springSecurityFilterChain.afterPropertiesSet();
+		}
+
+		@Override
+		public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+				throws IOException, ServletException {
+			this.doFilterDelegate.doFilter(request, response, chain);
+		}
+
+		@Override
+		public List<Filter> getFilters(String url) {
+			return this.springSecurityFilterChain.getFilters(url);
+		}
+
+		@Override
+		public List<SecurityFilterChain> getFilterChains() {
+			return this.springSecurityFilterChain.getFilterChains();
+		}
+
+		@Override
+		public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
+			this.springSecurityFilterChain.setSecurityContextHolderStrategy(securityContextHolderStrategy);
+		}
+
+		@Override
+		public void setFilterChainValidator(FilterChainValidator filterChainValidator) {
+			this.springSecurityFilterChain.setFilterChainValidator(filterChainValidator);
+		}
+
+		@Override
+		public void setFilterChainDecorator(FilterChainDecorator filterChainDecorator) {
+			this.springSecurityFilterChain.setFilterChainDecorator(filterChainDecorator);
+		}
+
+		@Override
+		public void setFirewall(HttpFirewall firewall) {
+			this.springSecurityFilterChain.setFirewall(firewall);
+		}
+
+		@Override
+		public void setRequestRejectedHandler(RequestRejectedHandler requestRejectedHandler) {
+			this.springSecurityFilterChain.setRequestRejectedHandler(requestRejectedHandler);
 		}
 
 		/**
@@ -212,7 +267,7 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
 		 * @return
 		 */
 		private List<? extends Filter> getFilters(HttpServletRequest request) {
-			List<SecurityFilterChain> filterChains = getFilterChainProxy().getFilterChains();
+			List<SecurityFilterChain> filterChains = this.springSecurityFilterChain.getFilterChains();
 			for (SecurityFilterChain chain : filterChains) {
 				if (chain.matches(request)) {
 					return chain.getFilters();
@@ -222,11 +277,14 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
 		}
 
 		/**
-		 * Used by Spring Security's Test support to find the FilterChainProxy
-		 * @return
+		 * Creates the Filter to delegate to for doFilter
+		 * @param filters the Filters to delegate to.
+		 * @return the Filter for doFilter
 		 */
-		private FilterChainProxy getFilterChainProxy() {
-			return this.springSecurityFilterChain;
+		private static Filter createDoFilterDelegate(List<? extends Filter> filters) {
+			CompositeFilter delegate = new CompositeFilter();
+			delegate.setFilters(filters);
+			return delegate;
 		}
 
 		/**