123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- [[jc-webflux]]
- = 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:
- * Hello WebFlux {gh-samples-url}/reactive/webflux/java/hello-security[hellowebflux]
- * Hello WebFlux.Fn {gh-samples-url}/reactive/webflux-fn/hello-security[hellowebfluxfn]
- * Hello WebFlux Method {gh-samples-url}/reactive/webflux/java/method[hellowebflux-method]
- == Minimal WebFlux Security Configuration
- The following listing shows a minimal WebFlux Security configuration:
- .Minimal WebFlux Security Configuration
- ====
- .Java
- [source,java,role="primary"]
- -----
- @EnableWebFluxSecurity
- public class HelloWebfluxSecurityConfig {
- @Bean
- public MapReactiveUserDetailsService userDetailsService() {
- UserDetails user = User.withDefaultPasswordEncoder()
- .username("user")
- .password("user")
- .roles("USER")
- .build();
- return new MapReactiveUserDetailsService(user);
- }
- }
- -----
- .Kotlin
- [source,kotlin,role="secondary"]
- -----
- @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.
- == Explicit WebFlux Security Configuration
- The following page shows an explicit version of the minimal WebFlux Security configuration:
- .Explicit WebFlux Security Configuration
- ====
- .Java
- [source,java,role="primary"]
- -----
- @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();
- }
- }
- -----
- .Kotlin
- [source,kotlin,role="secondary"]
- -----
- @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 { }
- }
- }
- }
- -----
- ====
- This configuration explicitly sets up all the same things as our minimal configuration.
- From here, you can more easily make changes to the defaults.
- You can find more examples of explicit configuration in unit tests, by searching for https://github.com/spring-projects/spring-security/search?q=path%3Aconfig%2Fsrc%2Ftest%2F+EnableWebFluxSecurity[`EnableWebFluxSecurity` in the `config/src/test/` directory].
- [[jc-webflux-multiple-filter-chains]]
- === Multiple Chains Support
- You can configure multiple `SecurityWebFilterChain` instances to separate configuration by `RequestMatcher` instances.
- For example, you can isolate configuration for URLs that start with `/api`:
- ====
- .Java
- [source,java,role="primary"]
- ----
- @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());
- }
- }
- ----
- .Kotlin
- [source,kotlin,role="secondary"]
- ----
- @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.
- 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.
|