skip to content

What is DelegatingFilterProxy and why does Spring Security need it?

level: juniorimportance: must knowfreq 70%

answer

  1. container Filter that holds no logic
  2. looks up Spring bean by name, delegates doFilter
  3. delegate = springSecurityFilterChain (FilterChainProxy)
  4. lazy lookup -> defers to ApplicationContext readiness
  5. bridge container lifecycle <-> Spring beans

basics

~20 s

DelegatingFilterProxy is a servlet Filter registered with the container that forwards requests to a Spring-managed filter bean (the security filter chain). It lets Spring beans act as filters even though the container created the proxy.

solid answer

~40 s

DelegatingFilterProxy is a standard jakarta.servlet.Filter that the servlet container registers and manages, but it does no filtering itself. On each request it looks up a Spring bean by name from the WebApplicationContext and delegates doFilter to it. Spring Security registers one named springSecurityFilterChain (a FilterChainProxy). This bridges two worlds: the container owns the filter lifecycle and knows about Filters at startup, while Spring Security's real logic lives in beans created and wired by the ApplicationContext. Without the proxy, the container would need to instantiate the security filter directly, losing dependency injection, AOP, and Spring lifecycle. It also defers bean lookup until the first request (or context readiness), so the Spring context can finish initializing before the filter is used.

go deeper

for a junior

Know it's a servlet filter that forwards to a Spring bean, and the bean is the security filter chain.

for a middle

Explain the name wiring (springSecurityFilterChain / FilterChainProxy) and that Boot auto-registers it.

for a senior

Articulate the two ownership models (container vs ApplicationContext) and why bridging is necessary for DI/AOP/lifecycle.

for a principal

Discuss deferred initialization, root-vs-child context lookup, targetFilterLifecycle, and the full delegation chain including FilterChainProxy selection.

## The problem it solves A servlet container (Tomcat, Jetty, etc.) manages the lifecycle of `jakarta.servlet.Filter` instances: it instantiates them, calls `init()`, `doFilter()`, and `destroy()`. Filters are typically declared in `web.xml` or via `ServletContext` registration at startup. But Spring Security's real filtering logic lives in **Spring beans** — objects created, dependency-injected, and lifecycle-managed by the Spring `ApplicationContext`, not by the container. These two ownership models don't naturally meet: the container doesn't know about Spring beans, and Spring beans aren't containers filters. ## What DelegatingFilterProxy is `org.springframework.web.filter.DelegatingFilterProxy` is itself a real `Filter` that the container registers and manages. But it contains **no security logic**. Its only job is to look up a Spring bean (by name) from the Spring `WebApplicationContext` and delegate `doFilter(...)` calls to that bean. So the container manages a lightweight proxy, and the proxy forwards to a fully Spring-managed delegate. ## How the name wiring works - The proxy has a **target bean name**. By default it's the filter's registered name; you can override it via the `targetBeanName` init-param. - Spring Security registers the proxy under the name **`springSecurityFilterChain`**, and the delegate bean is also named **`springSecurityFilterChain`** — an instance of `org.springframework.security.web.FilterChainProxy`. - In classic setups, `AbstractSecurityWebApplicationInitializer` (or `web.xml`) registers the `DelegatingFilterProxy` named `springSecurityFilterChain`, mapped to `/*`. - In Spring Boot, `SecurityFilterAutoConfiguration` registers a `DelegatingFilterProxyRegistrationBean` that wires the proxy to the `springSecurityFilterChain` bean automatically — you never write this by hand. ## Deferred initialization — the key mechanism At container startup the target Spring bean may not exist yet (the `ApplicationContext` may still be initializing). `DelegatingFilterProxy` therefore **lazily looks up the delegate on the first request** rather than in `init()`. It finds the `WebApplicationContext` (by default via `WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)`, i.e., the root context), fetches the bean, and caches it. This deferral is why the proxy exists at all: it lets the servlet filter chain be assembled at startup while the actual security beans come online later, driven by the Spring context lifecycle. ## Delegate lifecycle By default the proxy does **not** invoke `init()`/`destroy()` on the delegate — Spring manages the bean's lifecycle. You can opt into invoking the servlet `Filter.init/destroy` on the delegate via the `targetFilterLifecycle` init-param (default `false`). ## Which context does it search? By default the **root** `WebApplicationContext` (the one created by `ContextLoaderListener`). You can point it at a specific context with the `contextAttribute` init-param. In Boot there is a single context, so this rarely matters. ## The full chain of delegation `Container filter chain` -> `DelegatingFilterProxy` -> `FilterChainProxy` (the `springSecurityFilterChain` bean) -> matched `SecurityFilterChain` -> ordered list of security filters (e.g., `SecurityContextHolderFilter`, `CsrfFilter`, `UsernamePasswordAuthenticationFilter`, `AuthorizationFilter`). Note the two-level indirection: the proxy bridges container->Spring, and `FilterChainProxy` then selects among possibly multiple `SecurityFilterChain`s by request matcher. ## Gotchas - Confusing `DelegatingFilterProxy` (the bridge) with `FilterChainProxy` (the actual dispatcher). Only the latter contains security filters. - Bean-name mismatch: if the `targetBeanName` doesn't resolve to a bean, you get a `NoSuchBeanDefinitionException` on first request. - Registering the proxy with the wrong URL mapping (must cover all secured paths, typically `/*`). - In multi-context apps, expecting the delegate in the child (DispatcherServlet) context when it lives in the root context. ## When you touch it Almost never directly in Boot. You encounter it when: reading stack traces, doing pure servlet/`web.xml` setups, adding custom filters that must be Spring beans, or debugging why a filter isn't being invoked.

  • What is the actual bean the proxy delegates to in Spring Security?
    A FilterChainProxy registered as the bean springSecurityFilterChain, which then dispatches to one of the SecurityFilterChain instances based on request matching.
  • In a Spring Boot app, who registers the DelegatingFilterProxy?
    SecurityFilterAutoConfiguration registers a DelegatingFilterProxyRegistrationBean that wires the proxy to the springSecurityFilterChain bean; you don't write it yourself.

saying these in an interview costs you the question

  • Saying DelegatingFilterProxy contains the security filters
  • Thinking it does the authentication/authorization itself
  • Believing the servlet container instantiates the security beans directly

context