WebFlux Security

Spring Security’s WebFlux support relies on a WebFilter and works the same for Spring WebFlux and Spring WebFlux.Fn. A few sample applications demonstrate the code:spring-doc.cn

Minimal WebFlux Security Configuration

The following listing shows a minimal WebFlux Security configuration:spring-doc.cn

Minimal WebFlux Security Configuration
@Configuration
@EnableWebFluxSecurity
public class HelloWebfluxSecurityConfig {

	@Bean
	public MapReactiveUserDetailsService userDetailsService() {
		UserDetails user = User.withDefaultPasswordEncoder()
			.username("user")
			.password("user")
			.roles("USER")
			.build();
		return new MapReactiveUserDetailsService(user);
	}
}
@Configuration
@EnableWebFluxSecurity
class HelloWebfluxSecurityConfig {

    @Bean
    fun userDetailsService(): ReactiveUserDetailsService {
        val userDetails = User.withDefaultPasswordEncoder()
                .username("user")
                .password("user")
                .roles("USER")
                .build()
        return MapReactiveUserDetailsService(userDetails)
    }
}

This configuration provides form and HTTP basic authentication, sets up authorization to require an authenticated user for accessing any page, sets up a default login page and a default logout page, sets up security related HTTP headers, adds CSRF protection, and more.spring-doc.cn

Explicit WebFlux Security Configuration

The following page shows an explicit version of the minimal WebFlux Security configuration:spring-doc.cn

Explicit WebFlux Security Configuration
@Configuration
@EnableWebFluxSecurity
public class HelloWebfluxSecurityConfig {

	@Bean
	public MapReactiveUserDetailsService userDetailsService() {
		UserDetails user = User.withDefaultPasswordEncoder()
			.username("user")
			.password("user")
			.roles("USER")
			.build();
		return new MapReactiveUserDetailsService(user);
	}

	@Bean
	public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
		http
			.authorizeExchange(exchanges -> exchanges
			    .anyExchange().authenticated()
			)
			.httpBasic(withDefaults())
			.formLogin(withDefaults());
		return http.build();
	}
}
import org.springframework.security.config.web.server.invoke

@Configuration
@EnableWebFluxSecurity
class HelloWebfluxSecurityConfig {

    @Bean
    fun userDetailsService(): ReactiveUserDetailsService {
        val userDetails = User.withDefaultPasswordEncoder()
                .username("user")
                .password("user")
                .roles("USER")
                .build()
        return MapReactiveUserDetailsService(userDetails)
    }

    @Bean
    fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
        return http {
            authorizeExchange {
                authorize(anyExchange, authenticated)
            }
            formLogin { }
            httpBasic { }
        }
    }
}
Make sure to import the org.springframework.security.config.web.server.invoke function to enable the Kotlin DSL in your class, as the IDE will not always auto-import the method, causing compilation issues.

This configuration explicitly sets up all the same things as our minimal configuration. From here, you can more easily make changes to the defaults.spring-doc.cn

You can find more examples of explicit configuration in unit tests, by searching for EnableWebFluxSecurity in the config/src/test/ directory.spring-doc.cn

Multiple Chains Support

You can configure multiple SecurityWebFilterChain instances to separate configuration by RequestMatcher instances.spring-doc.cn

For example, you can isolate configuration for URLs that start with /api:spring-doc.cn

@Configuration
@EnableWebFluxSecurity
static class MultiSecurityHttpConfig {

    @Order(Ordered.HIGHEST_PRECEDENCE)                                                      (1)
    @Bean
    SecurityWebFilterChain apiHttpSecurity(ServerHttpSecurity http) {
        http
            .securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/**"))      (2)
            .authorizeExchange((exchanges) -> exchanges
                .anyExchange().authenticated()
            )
            .oauth2ResourceServer(OAuth2ResourceServerSpec::jwt);                           (3)
        return http.build();
    }

    @Bean
    SecurityWebFilterChain webHttpSecurity(ServerHttpSecurity http) {                       (4)
        http
            .authorizeExchange((exchanges) -> exchanges
                .anyExchange().authenticated()
            )
            .httpBasic(withDefaults());                                                     (5)
        return http.build();
    }

    @Bean
    ReactiveUserDetailsService userDetailsService() {
        return new MapReactiveUserDetailsService(
                PasswordEncodedUser.user(), PasswordEncodedUser.admin());
    }

}
import org.springframework.security.config.web.server.invoke

@Configuration
@EnableWebFluxSecurity
open class MultiSecurityHttpConfig {
    @Order(Ordered.HIGHEST_PRECEDENCE)                                                      (1)
    @Bean
    open fun apiHttpSecurity(http: ServerHttpSecurity): SecurityWebFilterChain {
        return http {
            securityMatcher(PathPatternParserServerWebExchangeMatcher("/api/**"))           (2)
            authorizeExchange {
                authorize(anyExchange, authenticated)
            }
            oauth2ResourceServer {
                jwt { }                                                                     (3)
            }
        }
    }

    @Bean
    open fun webHttpSecurity(http: ServerHttpSecurity): SecurityWebFilterChain {            (4)
        return http {
            authorizeExchange {
                authorize(anyExchange, authenticated)
            }
            httpBasic { }                                                                   (5)
        }
    }

    @Bean
    open fun userDetailsService(): ReactiveUserDetailsService {
        return MapReactiveUserDetailsService(
            PasswordEncodedUser.user(), PasswordEncodedUser.admin()
        )
    }
}
1 Configure a SecurityWebFilterChain with an @Order to specify which SecurityWebFilterChain Spring Security should consider first
2 Use PathPatternParserServerWebExchangeMatcher to state that this SecurityWebFilterChain will only apply to URL paths that start with /api/
3 Specify the authentication mechanisms that will be used for /api/** endpoints
4 Create another instance of SecurityWebFilterChain with lower precedence to match all other URLs
5 Specify the authentication mechanisms that will be used for the rest of the application

Spring Security selects one SecurityWebFilterChain @Bean for each request. It matches the requests in order by the securityMatcher definition.spring-doc.cn

In this case, that means that, if the URL path starts with /api, Spring Security uses apiHttpSecurity. If the URL does not start with /api, Spring Security defaults to webHttpSecurity, which has an implied securityMatcher that matches any request.spring-doc.cn