Spring Security: DelegatingFilterProxy & SecurityFilterChain
- Last updated
- Prerequisites:
- Spring Boot web basics
- Understanding of servlet filters and security concepts
- spring
- spring-security
- filter-chain
- delegating-filter-proxy
- authentication
- authorization
Read at your depth
The practical view
Spring Security is implemented as a chain of servlet filters. The entry point is DelegatingFilterProxy, a servlet filter registered in the container that delegates to a Spring-managed FilterChainProxy bean. Inside, SecurityFilterChain defines an ordered list of security filters: authentication filters (UsernamePasswordAuthenticationFilter), authorization (AuthorizationFilter), CSRF, CORS, etc. In Spring Security 6 you configure with a SecurityFilterChain bean: @Bean SecurityFilterChain filterChain(HttpSecurity http) { return http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(a -> a.anyRequest().authenticated()).build(); }. Multiple chains can match different URL patterns.
The same idea in other frameworks
N/A — server-side Spring Security concern.N/A — Spring concern.N/A — Spring concern.N/A — Spring concern.Legacy vs modern
Default security config vs explicit SecurityFilterChain
Relying on defaults is opaque and often too restrictive; an explicit SecurityFilterChain bean makes the chain visible and tunable.
@SpringBootApplication
public class App { /* ❌ OLD: no SecurityFilterChain — defaults apply */ }@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// ✅ NEW: visible, ordered chain
return http.authorizeHttpRequests(a -> a
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated())
.formLogin(Customizer.withDefaults())
.build();
}Interview gotchas
Context
This tests the container-to-Spring bridge — interviewers want the lifecycle and bean-lookup rationale, which explains why security filters are Spring-managed beans.
The mechanical answer
DelegatingFilterProxy is a servlet filter (registered with the servlet container) that delegates all filtering to a Spring bean — by default the FilterChainProxy bean found in the ApplicationContext. The container only knows the proxy; the actual security filters live in the Spring context. This decouples the container lifecycle from Spring's: the proxy can be initialized before the Spring context is fully ready, and it lazily looks up the delegate bean when the first request arrives. It also lets the security chain use Spring features (DI, AOP, profiles) that a plain servlet filter cannot. FilterChainProxy then dispatches to the matching SecurityFilterChain. Without this bridge, the container would have no way to invoke Spring-managed, DI-dependent security filters in the correct order.
Trap
The naive answer is 'DelegatingFilterProxy is just the first security filter'. It's a bridge that doesn't do security itself — it routes to the Spring FilterChainProxy. Another trap: thinking filters are registered directly in the container — they are beans managed by Spring and invoked via the proxy. Candidates who explain the lifecycle decoupling and bean delegation show real understanding.
Context
This probes the chain resolution and ordering semantics — interviewers want the RequestMatcher selection and the per-filter ordering that makes authentication-before-authorization work.
The mechanical answer
FilterChainProxy holds an ordered list of SecurityFilterChain beans. For each request, it iterates the chains and runs the FIRST one whose RequestMatcher matches the request (e.g. securityMatcher("/api/**")); the remaining chains are skipped. This is why chain order matters: a broad matcher (anyRequest) placed first would swallow requests meant for a more specific chain. Within a chain, the filters execute in a strict documented order (e.g. SecurityContextHolderFilter early so later filters can read the authenticated principal, then CSRF, then authentication filters, then authorization last). This ordering guarantees that by the time authorization runs, authentication has already populated the SecurityContext. Breaking the order (or having overlapping matchers) silently changes security behavior.
Trap
The naive answer is 'all chains run for every request'. Only the first matching chain runs. Another trap: defining a catch-all chain first (anyRequest) that shadows a more specific /api chain — requests hit the wrong chain and get wrong security rules. Candidates who describe the first-match selection and filter ordering show real Spring Security mastery.