Explain the difference between DelegatingFilterProxy and FilterChainProxy.
answer
- proxy = bridge (spring-web); FilterChainProxy = dispatcher (spring-security-web)
- proxy holds no filters
- FilterChainProxy holds List<SecurityFilterChain>
- first matching chain wins
- container -> proxy -> FilterChainProxy -> chain -> filters
basics
~10 sDelegatingFilterProxy is the container-registered bridge that forwards to a Spring bean. FilterChainProxy is that bean — the Spring-managed filter that holds the security filter chains and runs the ordered security filters.
solid answer
~40 sThey are two different objects doing two different jobs. DelegatingFilterProxy is a thin servlet Filter registered with and managed by the container; it has no security logic and simply delegates each request to a Spring bean looked up by name. FilterChainProxy is that delegate bean, registered as springSecurityFilterChain. It is where Spring Security actually lives: it holds a list of SecurityFilterChain instances, matches the incoming request against each chain's RequestMatcher, and invokes the ordered security filters (SecurityContextHolderFilter, CsrfFilter, authentication filters, AuthorizationFilter, etc.) of the first matching chain. So the flow is container -> DelegatingFilterProxy -> FilterChainProxy -> matched SecurityFilterChain -> individual filters. The proxy bridges container-to-Spring; FilterChainProxy dispatches within Spring Security.
go deeper
Know they're different: one bridges, one dispatches.
Explain the delegation flow and that FilterChainProxy selects the first matching SecurityFilterChain.
Discuss multi-chain routing, @Order, and the SecurityContext clearing in FilterChainProxy.
Reason about chain-shadowing pitfalls, VirtualFilterChain mechanics, and why bridging and routing are separated.
## Two objects, two responsibilities ### DelegatingFilterProxy - Package: `org.springframework.web.filter.DelegatingFilterProxy` (part of spring-web, NOT spring-security). - Registered with the servlet container (via `web.xml`, `AbstractSecurityWebApplicationInitializer`, or a `DelegatingFilterProxyRegistrationBean` in Boot). - Managed by the container's filter lifecycle. - Holds no filtering logic — it looks up a target bean by name in the `WebApplicationContext` and forwards `doFilter`. - Purpose: **bridge** the container filter world to Spring-managed beans, with deferred (lazy, cached) bean lookup. ### FilterChainProxy - Package: `org.springframework.security.web.FilterChainProxy` (part of spring-security-web). - Is a Spring bean, conventionally named **`springSecurityFilterChain`** — the exact target the proxy delegates to. - Holds a `List<SecurityFilterChain>`. Each `SecurityFilterChain` pairs a `RequestMatcher` with an ordered `List<Filter>`. - On each request it iterates the chains, picks the **first** whose matcher matches, and runs that chain's filters in order via an internal `VirtualFilterChain`. - Also performs cross-cutting duties: clearing the `SecurityContextHolder` after the request, firing `FilterChain` proceed, request/response wrapping. ## The chain of delegation ``` HTTP request -> Servlet container filter chain -> DelegatingFilterProxy (container-managed bridge) -> FilterChainProxy (Spring bean: springSecurityFilterChain) -> first matching SecurityFilterChain -> SecurityContextHolderFilter -> CsrfFilter -> UsernamePasswordAuthenticationFilter / BearerTokenAuthenticationFilter -> AuthorizationFilter -> ... then the app's own filters / DispatcherServlet ``` ## Why two layers? The proxy solves an ownership/lifecycle problem (container vs Spring). `FilterChainProxy` solves a **routing** problem: an app may define multiple `SecurityFilterChain` beans (e.g., one for `/api/**` using bearer tokens, one for everything else using form login). `FilterChainProxy` is what selects among them. Collapsing both jobs into one object would mix container bridging with security dispatch. ## Common confusion / gotchas - Candidates often say the proxy "contains the filters" — wrong; that's `FilterChainProxy`. - Only the **first** matching `SecurityFilterChain` runs; ordering of chains matters (`@Order` on the beans). A too-broad early chain can shadow later ones. - If no chain matches, no security filters run (in modern Boot a default chain matches `/**`). - `FilterChainProxy` clears the `SecurityContext` in a `finally` block after the request — important for thread-pool reuse. ## When you care Debugging security you'll set breakpoints in `FilterChainProxy.doFilter` to see chain selection, and check the `DelegatingFilterProxy` only when the whole security layer isn't invoked at all (registration/mapping issues).
- If an app has multiple SecurityFilterChain beans, how does FilterChainProxy decide which to use?It iterates chains in order and uses the first whose RequestMatcher matches the request; only that one chain's filters run, so bean @Order matters.
- Which library does each class come from?DelegatingFilterProxy is in spring-web; FilterChainProxy is in spring-security-web.
saying these in an interview costs you the question
- Saying DelegatingFilterProxy contains the security filters
- Thinking all matching SecurityFilterChains run instead of just the first
- Believing FilterChainProxy is registered with the servlet container directly