What is a SecurityFilterChain @Bean and how do you declare one in modern Spring Security?
answer
- @Bean returns http.build()
- HttpSecurity is an injected builder
- SecurityFilterChain = matcher + filter list
- Replaced WebSecurityConfigurerAdapter (dep 5.7, removed 6.0)
- FilterChainProxy holds all chains
basics
~10 sYou 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 sSince 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@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
Must know the @Bean + http.build() shape and that it replaced WebSecurityConfigurerAdapter.
Should explain HttpSecurity as an injected builder and that returning any chain disables Boot's default.
Should connect the bean to FilterChainProxy and RequestMatcher + filter-list structure.
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.