skip to content

SecurityFilterChain Bean & Lambda DSL

Modern configuration is a SecurityFilterChain bean built with the lambda DSL on HttpSecurity, replacing the removed WebSecurityConfigurerAdapter. Interviewers check you have made this migration rather than pasting Spring Security 5 examples.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is a SecurityFilterChain @Bean and how do you declare one in modern Spring Security?

level: juniorimportance: must knowfreq 80%

answer

  1. @Bean returns http.build()
  2. HttpSecurity is an injected builder
  3. SecurityFilterChain = matcher + filter list
  4. Replaced WebSecurityConfigurerAdapter (dep 5.7, removed 6.0)
  5. FilterChainProxy holds all chains

basics

~10 s

You write a method annotated with @Bean that takes an HttpSecurity object, configures the rules on it, and returns http.build(), which produces a SecurityFilterChain. Spring registers it to secure your HTTP requests.

solid answer

~40 s

Since Spring Security 5.7 the idiomatic way to configure web security is a @Bean method returning a SecurityFilterChain. You inject the auto-configured HttpSecurity builder, call configuration methods on it (authorizeHttpRequests, formLogin, httpBasic, csrf, etc.), and finish with http.build() which assembles and returns the SecurityFilterChain. A SecurityFilterChain pairs a RequestMatcher (which requests it handles) with an ordered list of Servlet filters that enforce authentication and authorization. This replaced the old WebSecurityConfigurerAdapter subclass approach, which was deprecated in 5.7 and removed in 6.0. The bean lives in a @Configuration class, usually annotated @EnableWebSecurity. This component-based style is more testable and composable — you can define several such beans and Spring wires them all into the FilterChainProxy.

code

java · 15 lines
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/", "/public/**").permitAll()
                .anyRequest().authenticated())
            .formLogin(Customizer.withDefaults())
            .httpBasic(Customizer.withDefaults());
        return http.build();
    }
}

go deeper

for a junior

Must know the @Bean + http.build() shape and that it replaced WebSecurityConfigurerAdapter.

for a middle

Should explain HttpSecurity as an injected builder and that returning any chain disables Boot's default.

for a senior

Should connect the bean to FilterChainProxy and RequestMatcher + filter-list structure.

for a principal

Frames it as the composable, DI-friendly successor enabling multiple scoped chains and testability.

**The big picture.** Spring Security works by inserting a chain of Servlet `Filter`s in front of your application. A `SecurityFilterChain` is an interface that bundles two things: (1) a `RequestMatcher` deciding *which* HTTP requests this chain applies to, and (2) an ordered `List<Filter>` that actually do the security work (CSRF checking, authentication, authorization, etc.). At the very front sits a single `FilterChainProxy` (registered as the `springSecurityFilterChain` bean) that holds all your `SecurityFilterChain`s and delegates each incoming request to the first one whose matcher matches. **How you declare it.** In modern Spring Security you write a `@Configuration` class (typically annotated `@EnableWebSecurity`, though Spring Boot enables it automatically) containing a method like: ```java @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .httpBasic(Customizer.withDefaults()); return http.build(); } ``` Key mechanics: - **`HttpSecurity`** is a *builder*. Spring auto-configures one and injects it as a method parameter (it is prototype-scoped, so each bean method gets a fresh one). You never `new` it. - Each configuration method (`authorizeHttpRequests`, `formLogin`, `csrf`, `cors`, `sessionManagement`, `oauth2Login`…) registers or tweaks a specific filter. - **`http.build()`** locks the builder and produces the immutable `SecurityFilterChain`. You must return this. - The method declares `throws Exception` because `build()` and many configurers can throw. **Why it replaced `WebSecurityConfigurerAdapter`.** Before 5.7 you subclassed `WebSecurityConfigurerAdapter` and overrode `configure(HttpSecurity)`. That forced an inheritance model, made multiple chains awkward, and hid the object you were producing. The adapter was **deprecated in Spring Security 5.7** and **removed in 6.0**. The bean approach exposes the actual `SecurityFilterChain` object, plays nicely with dependency injection, and lets you define multiple chains as ordinary beans. **Gotchas for beginners.** - Return type must be `SecurityFilterChain`, and you must actually `return http.build()` — forgetting it is a compile error, but returning the wrong thing (e.g. the `http` builder) will not compile either. - If you declare *any* `SecurityFilterChain` bean, Spring Boot backs off its default chain — so your bean must configure everything you need (auth mechanism, permitAll paths, etc.), or requests may become unexpectedly locked down or wide open. - Configuration methods must be called on the injected `http`, not a new instance. **When to use.** Always, for any Spring Security 5.7+ / 6.x application. There is no modern alternative — the adapter is gone.

  • What does http.build() actually return and why must you call it?
    It finalizes the HttpSecurity builder and produces the immutable SecurityFilterChain object (matcher + ordered filters). Without it you have only a half-configured builder, not a bean the container can register.
  • What happens to Spring Boot's default security if you declare your own SecurityFilterChain bean?
    Boot's auto-configured default chain backs off. Your bean becomes authoritative, so you must configure the authentication mechanism and authorization rules yourself — otherwise you can accidentally lock everything down or leave it open.

context

open as a page

What is the Lambda DSL in Spring Security and why is it preferred over the old chained-and method style?

level: middleimportance: must knowfreq 70%

basics

~20 s

The Lambda DSL configures each area by passing a lambda (a Customizer) into methods like authorizeHttpRequests(auth -> ...). It groups related settings clearly and avoids the ambiguous .and() chaining of the old style, which is now deprecated.

open as a page

How does authorizeHttpRequests work, and why does the order of its matcher rules matter?

level: middleimportance: should knowfreq 65%

basics

~10 s

authorizeHttpRequests defines authorization rules by matching request paths to access rules like permitAll() or authenticated(). Rules are evaluated top-to-bottom and the first match wins, so specific rules must come before broad ones like anyRequest().

open as a page

How do you define multiple SecurityFilterChain beans, and how does Spring decide which one handles a request?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Declare several SecurityFilterChain beans, each scoped with http.securityMatcher(...) to a URL subset, and order them with @Order. The FilterChainProxy tries them in order and the first chain whose matcher matches handles the request — only one chain runs per request.

open as a page

When should you use authorizeHttpRequests().permitAll() versus WebSecurityCustomizer web.ignoring(), and how are HttpSecurity, WebSecurity, and FilterChainProxy related?

level: principalimportance: nice to knowfreq 35%

basics

~20 s

permitAll() lets a request through but still runs the security filter chain (CSRF, headers, etc.). web.ignoring() (WebSecurityCustomizer) tells Spring to skip the entire chain for those paths. Prefer permitAll(); reserve ignoring() for truly static, security-irrelevant resources.

open as a page