Understanding Spring Security’s Core FilterChainProxy and Adding Custom Filters
This article explains how Spring Security builds its core FilterChainProxy and DefaultSecurityFilterChain, outlines three ways to create custom security filter chains, and demonstrates how to implement and register a custom filter within the Spring Security filter chain.
Core Filter Creation Principle
Spring Security relies on a chain of Filter objects to handle CSRF, authentication, authorization, session management, and other concerns. These filters are encapsulated in DefaultSecurityFilterChain , which is ultimately added to a FilterChainProxy bean named springSecurityFilterChain .
Creation of FilterChainProxy and the default filter chain follows these steps:
public class WebSecurityConfiguration {
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
// Detect custom SecurityConfigurer (WebSecurityConfigurerAdapter) or custom SecurityFilterChain beans
boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
boolean hasFilterChain = !this.securityFilterChains.isEmpty();
Assert.state(!(hasConfigurers && hasFilterChain), "Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.");
if (!hasConfigurers && !hasFilterChain) {
WebSecurityConfigurerAdapter adapter = this.objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter() {});
this.webSecurity.apply(adapter);
}
// Apply any custom WebSecurityCustomizer beans
for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
customizer.customize(this.webSecurity);
}
// Build the FilterChainProxy
return this.webSecurity.build();
}
}The WebSecurity#build method assembles the final FilterChainProxy :
public final class WebSecurity {
private final List<RequestMatcher> ignoredRequests = new ArrayList<>();
protected Filter performBuild() throws Exception {
int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);
for (RequestMatcher ignoredRequest : this.ignoredRequests) {
securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
}
for (SecurityBuilder<? extends SecurityFilterChain> builder : this.securityFilterChainBuilders) {
securityFilterChains.add(builder.build());
}
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
filterChainProxy.afterPropertiesSet();
return filterChainProxy;
}
}Ways to Create a DefaultSecurityFilterChain
There are three main approaches:
Custom SecurityFilterChain bean – when this bean exists, a WebSecurityConfigurerAdapter cannot be used.
@Component
public class CustomSecurityFilterChain implements SecurityFilterChain {
@Override
public boolean matches(HttpServletRequest request) { return false; }
@Override
public List<Filter> getFilters() { return new ArrayList<>(); }
}Custom WebSecurityCustomizer bean – used to define URIs that should be ignored by security.
@Component
public class CustomWebSecurity implements WebSecurityCustomizer {
@Override
public void customize(WebSecurity web) {
web.ignoring().antMatchers("/demos/home");
}
}Custom WebSecurityConfigurerAdapter subclass – the most common way; it contributes an HttpSecurity instance to the security filter chain builders.
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// ... override configure(HttpSecurity http) ...
}Custom Filter Implementation
To add your own processing logic, create a filter that extends OncePerRequestFilter and register it in the security configuration.
@Component
public class AutoAuthenticationFilter extends OncePerRequestFilter {
@Resource
private AuthenticationManager authenticationManager;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken("admin", "123123");
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
Authentication auth = authenticationManager.authenticate(authToken);
if (auth != null) {
SecurityContextHolder.getContext().setAuthentication(auth);
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
}
System.out.println("--------------------------Auto Authentication Filter...");
filterChain.doFilter(request, response);
}
}Register the filter before UsernamePasswordAuthenticationFilter in WebSecurityConfigurerAdapter#configure(HttpSecurity http):
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private AutoAuthenticationFilter authFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class);
}
}Summary
Understanding the implementation details of core filter creation (FilterChainProxy and DefaultSecurityFilterChain).
Applying custom filters to extend Spring Security’s authentication flow.
Next article will cover database‑based user authentication.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
