Skip to content

Commit 142b268

Browse files
committed
Use CompositeFilterChainProxy
By extending FilterChainProxy CompositeFilterChainProxy is more passive since users often depend on the type of the springSecurityFilterChain Bean being FilterChainProxy (even though it can already be other types - when debug is enabled). Issue gh-14128
1 parent 70dfb3d commit 142b268

File tree

1 file changed

+78
-20
lines changed

1 file changed

+78
-20
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java

+78-20
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,21 @@
1616

1717
package org.springframework.security.config.annotation.web.configuration;
1818

19+
import java.io.IOException;
1920
import java.util.List;
2021

2122
import jakarta.servlet.Filter;
23+
import jakarta.servlet.FilterChain;
24+
import jakarta.servlet.ServletException;
25+
import jakarta.servlet.ServletRequest;
26+
import jakarta.servlet.ServletResponse;
2227
import jakarta.servlet.http.HttpServletRequest;
2328

2429
import org.springframework.beans.BeanMetadataElement;
2530
import org.springframework.beans.BeansException;
2631
import org.springframework.beans.factory.FactoryBean;
2732
import org.springframework.beans.factory.config.BeanDefinition;
2833
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
29-
import org.springframework.beans.factory.config.RuntimeBeanReference;
3034
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
3135
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
3236
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
@@ -42,6 +46,8 @@
4246
import org.springframework.security.web.SecurityFilterChain;
4347
import org.springframework.security.web.access.HandlerMappingIntrospectorRequestTransformer;
4448
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
49+
import org.springframework.security.web.firewall.HttpFirewall;
50+
import org.springframework.security.web.firewall.RequestRejectedHandler;
4551
import org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver;
4652
import org.springframework.security.web.method.annotation.CsrfTokenArgumentResolver;
4753
import org.springframework.security.web.method.annotation.CurrentSecurityContextArgumentResolver;
@@ -135,21 +141,18 @@ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) t
135141
registry.registerBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + "RequestTransformer",
136142
hmiRequestTransformer);
137143

138-
String filterChainProxyBeanName = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME
139-
+ "Proxy";
140144
BeanDefinition filterChainProxy = registry
141145
.getBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
142-
registry.registerBeanDefinition(filterChainProxyBeanName, filterChainProxy);
143146

144147
BeanDefinitionBuilder hmiCacheFilterBldr = BeanDefinitionBuilder
145148
.rootBeanDefinition(HandlerMappingIntrospectorCachFilterFactoryBean.class)
146149
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
147150

148151
ManagedList<BeanMetadataElement> filters = new ManagedList<>();
149152
filters.add(hmiCacheFilterBldr.getBeanDefinition());
150-
filters.add(new RuntimeBeanReference(filterChainProxyBeanName));
153+
filters.add(filterChainProxy);
151154
BeanDefinitionBuilder compositeSpringSecurityFilterChainBldr = BeanDefinitionBuilder
152-
.rootBeanDefinition(SpringSecurityFilterCompositeFilter.class)
155+
.rootBeanDefinition(CompositeFilterChainProxy.class)
153156
.addConstructorArgValue(filters);
154157

155158
registry.removeBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
@@ -188,21 +191,73 @@ public Class<?> getObjectType() {
188191
}
189192

190193
/**
191-
* Extension to {@link CompositeFilter} to expose private methods used by Spring
192-
* Security's test support
194+
* Extends {@link FilterChainProxy} to provide as much passivity as possible but
195+
* delegates to {@link CompositeFilter} for
196+
* {@link #doFilter(ServletRequest, ServletResponse, FilterChain)}.
193197
*/
194-
static class SpringSecurityFilterCompositeFilter extends CompositeFilter {
198+
static class CompositeFilterChainProxy extends FilterChainProxy {
195199

196-
private FilterChainProxy springSecurityFilterChain;
200+
/**
201+
* Used for {@link #doFilter(ServletRequest, ServletResponse, FilterChain)}
202+
*/
203+
private final Filter doFilterDelegate;
197204

198-
SpringSecurityFilterCompositeFilter(List<? extends Filter> filters) {
199-
setFilters(filters); // for the parent
205+
private final FilterChainProxy springSecurityFilterChain;
206+
207+
/**
208+
* Creates a new instance
209+
* @param filters the Filters to delegate to. One of which must be
210+
* FilterChainProxy.
211+
*/
212+
CompositeFilterChainProxy(List<? extends Filter> filters) {
213+
this.doFilterDelegate = createDoFilterDelegate(filters);
214+
this.springSecurityFilterChain = findFilterChainProxy(filters);
200215
}
201216

202217
@Override
203-
public void setFilters(List<? extends Filter> filters) {
204-
super.setFilters(filters);
205-
this.springSecurityFilterChain = findFilterChainProxy(filters);
218+
public void afterPropertiesSet() {
219+
this.springSecurityFilterChain.afterPropertiesSet();
220+
}
221+
222+
@Override
223+
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
224+
throws IOException, ServletException {
225+
this.doFilterDelegate.doFilter(request, response, chain);
226+
}
227+
228+
@Override
229+
public List<Filter> getFilters(String url) {
230+
return this.springSecurityFilterChain.getFilters(url);
231+
}
232+
233+
@Override
234+
public List<SecurityFilterChain> getFilterChains() {
235+
return this.springSecurityFilterChain.getFilterChains();
236+
}
237+
238+
@Override
239+
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
240+
this.springSecurityFilterChain.setSecurityContextHolderStrategy(securityContextHolderStrategy);
241+
}
242+
243+
@Override
244+
public void setFilterChainValidator(FilterChainValidator filterChainValidator) {
245+
this.springSecurityFilterChain.setFilterChainValidator(filterChainValidator);
246+
}
247+
248+
@Override
249+
public void setFilterChainDecorator(FilterChainDecorator filterChainDecorator) {
250+
this.springSecurityFilterChain.setFilterChainDecorator(filterChainDecorator);
251+
}
252+
253+
@Override
254+
public void setFirewall(HttpFirewall firewall) {
255+
this.springSecurityFilterChain.setFirewall(firewall);
256+
}
257+
258+
@Override
259+
public void setRequestRejectedHandler(RequestRejectedHandler requestRejectedHandler) {
260+
this.springSecurityFilterChain.setRequestRejectedHandler(requestRejectedHandler);
206261
}
207262

208263
/**
@@ -212,7 +267,7 @@ public void setFilters(List<? extends Filter> filters) {
212267
* @return
213268
*/
214269
private List<? extends Filter> getFilters(HttpServletRequest request) {
215-
List<SecurityFilterChain> filterChains = getFilterChainProxy().getFilterChains();
270+
List<SecurityFilterChain> filterChains = this.springSecurityFilterChain.getFilterChains();
216271
for (SecurityFilterChain chain : filterChains) {
217272
if (chain.matches(request)) {
218273
return chain.getFilters();
@@ -222,11 +277,14 @@ private List<? extends Filter> getFilters(HttpServletRequest request) {
222277
}
223278

224279
/**
225-
* Used by Spring Security's Test support to find the FilterChainProxy
226-
* @return
280+
* Creates the Filter to delegate to for doFilter
281+
* @param filters the Filters to delegate to.
282+
* @return the Filter for doFilter
227283
*/
228-
private FilterChainProxy getFilterChainProxy() {
229-
return this.springSecurityFilterChain;
284+
private static Filter createDoFilterDelegate(List<? extends Filter> filters) {
285+
CompositeFilter delegate = new CompositeFilter();
286+
delegate.setFilters(filters);
287+
return delegate;
230288
}
231289

232290
/**

0 commit comments

Comments
 (0)