spring-security/docs/modules/ROOT/pages/reactive/configuration/webflux.adoc

228 lines
7.2 KiB
Plaintext
Raw Normal View History

[[jc-webflux]]
= WebFlux Security
Spring Security's WebFlux support relies on a `WebFilter` and works the same for Spring WebFlux and Spring WebFlux.Fn.
You can find a few sample applications that demonstrate the code below:
* 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
You can find a minimal WebFlux Security configuration below:
.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 log in page and a default log out page, sets up security related HTTP headers, CSRF protection, and more.
== Explicit WebFlux Security Configuration
You can find an explicit version of the minimal WebFlux Security configuration below:
.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 easily make the changes to the defaults.
2020-10-27 06:44:40 -04:00
You can find more examples of explicit configuration in unit tests, by searching 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``s.
For example, you can isolate configuration for URLs that start with `/api`, like so:
====
.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()
)
2021-06-17 09:39:33 -04:00
.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 will select one `SecurityWebFilterChain` `@Bean` for each request.
It will match the requests in order by the `securityMatcher` definition.
In this case, that means that if the URL path starts with `/api`, then Spring Security will use `apiHttpSecurity`.
If the URL does not start with `/api` then Spring Security will default to `webHttpSecurity`, which has an implied `securityMatcher` that matches any request.
2020-10-27 06:44:40 -04:00