What does @EnableWebFluxSecurity do, and how do you define a security configuration in a Spring WebFlux application?
answer
- reactive analogue of @EnableWebSecurity
- @Bean SecurityWebFilterChain
- ServerHttpSecurity DSL + .build()
- authorizeExchange, not authorizeHttpRequests
- Boot auto-configures a secure-everything default
basics
~10 s@EnableWebFluxSecurity turns on Spring Security for a reactive WebFlux app. You then declare a @Bean of type SecurityWebFilterChain that configures which URLs are protected and how users log in.
solid answer
~40 s@EnableWebFluxSecurity is the annotation that activates Spring Security for a reactive (WebFlux/Netty) application, importing the reactive security infrastructure. Instead of the servlet-based WebSecurityConfigurerAdapter/SecurityFilterChain, you expose a @Bean of type SecurityWebFilterChain, built from a ServerHttpSecurity object that Spring injects. On that object you use a fluent DSL — authorizeExchange(), httpBasic(), formLogin(), csrf(), etc. — and finish with .build(). In modern Spring Boot you often don't even write @EnableWebFluxSecurity yourself, because Boot's reactive security auto-configuration adds it once spring-boot-starter-security is on the classpath; you just provide the SecurityWebFilterChain bean to override the defaults (which otherwise secure every endpoint with HTTP Basic and a generated password).
code
java · 16 lines@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http
.authorizeExchange(exchange -> exchange
.pathMatchers("/public/**").permitAll()
.pathMatchers("/admin/**").hasRole("ADMIN")
.anyExchange().authenticated())
.httpBasic(Customizer.withDefaults())
.formLogin(Customizer.withDefaults())
.build();
}
}go deeper
Know the annotation turns on security and that you configure it with a SecurityWebFilterChain bean.
Should recall the ServerHttpSecurity DSL methods (authorizeExchange, httpBasic) and that Boot auto-configures a default chain.
Explain the WebFilter-based design vs servlet filters and why WebSecurityConfigurerAdapter never applied here.
Discuss layering multiple chains, ordering, and integrating with gateway/resource-server patterns in a fully reactive stack.
## What is WebFlux? Spring WebFlux is Spring's **reactive** web stack. Unlike Spring MVC (which runs on the Servlet API and a thread-per-request model), WebFlux runs on a non-blocking runtime (by default Netty) and processes requests as reactive streams using Project Reactor types **Mono** (0–1 value) and **Flux** (0–N values). Because there is no Servlet API, the classic servlet `Filter` chain does not exist — WebFlux uses its own **WebFilter** abstraction. ## @EnableWebFluxSecurity `@EnableWebFluxSecurity` is the annotation that **bootstraps Spring Security for a WebFlux app**. Placed on a `@Configuration` class, it imports the reactive security configuration (`WebFluxSecurityConfiguration` and related classes), which registers the core `WebFilter` — the `WebFilterChainProxy` / `SecurityWebFilterChain` machinery — into the WebFlux filter pipeline. This is the reactive counterpart of the servlet world's `@EnableWebSecurity`. With **Spring Boot** and `spring-boot-starter-security` on the classpath, reactive security **auto-configuration** already applies `@EnableWebFluxSecurity` for you and installs a default chain that: - requires authentication for **every** exchange, - enables **HTTP Basic** and **form login**, - generates a random password logged at startup (default user `user`). So you rarely type `@EnableWebFluxSecurity` explicitly; you add it only when you want full manual control or are outside Boot. ## SecurityWebFilterChain — the bean you define To customize security you declare a bean: ```java @Bean SecurityWebFilterChain chain(ServerHttpSecurity http) { ... } ``` `SecurityWebFilterChain` is an interface pairing a **matcher** (which requests it applies to) with an ordered list of `WebFilter`s. Defining this bean **replaces** Boot's default chain. ## ServerHttpSecurity — the builder `ServerHttpSecurity` is the reactive analogue of `HttpSecurity`. Spring provides it as an injectable object; you call fluent methods to configure features and then `.build()` to produce the `SecurityWebFilterChain`. Common methods: - `authorizeExchange(...)` — authorization rules per request (`pathMatchers(...).hasRole(...)`, `.authenticated()`, `.permitAll()`). Note it's **authorizeExchange**, not `authorizeHttpRequests`, and uses `ServerWebExchange`. - `httpBasic(...)`, `formLogin(...)`, `oauth2Login(...)`, `oauth2ResourceServer(...)`. - `csrf(...)`, `cors(...)`, `headers(...)`. ## Minimal example ```java @Configuration @EnableWebFluxSecurity public class SecurityConfig { @Bean SecurityWebFilterChain chain(ServerHttpSecurity http) { return http .authorizeExchange(e -> e .pathMatchers("/public/**").permitAll() .anyExchange().authenticated()) .httpBasic(Customizer.withDefaults()) .build(); } } ``` ## Gotchas - Adding `@EnableWebSecurity` (the servlet annotation) in a WebFlux app is wrong — it targets the servlet stack. - If both spring-webmvc and spring-webflux are on the classpath, Boot picks MVC by default, and reactive security won't activate; keep the stacks separate. - Configuration is **all bean-based** now — the deprecated/removed `WebSecurityConfigurerAdapter` was servlet-only and never existed for WebFlux. ## When to use Use this whenever you secure a reactive service (Netty-based microservice, API gateway, streaming endpoints). The building blocks — `@EnableWebFluxSecurity`, `SecurityWebFilterChain`, `ServerHttpSecurity` — are the entry point for everything else (authorization rules, authentication managers, user-details services).
- What is the servlet-stack equivalent of SecurityWebFilterChain?SecurityFilterChain, built from HttpSecurity (with @EnableWebSecurity). The WebFlux versions are SecurityWebFilterChain built from ServerHttpSecurity with @EnableWebFluxSecurity.
- If you add spring-boot-starter-security but define no beans, what happens?Boot's reactive security auto-config secures every exchange with HTTP Basic and form login, using a generated password for user 'user' printed to the console at startup.