| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 | 
							- [[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"]
 
- -----
 
- @Configuration
 
- @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"]
 
- -----
 
- @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.
 
- == 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"]
 
- -----
 
- 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 { }
 
-         }
 
-     }
 
- }
 
- -----
 
- ====
 
- [NOTE]
 
- Make sure that you import the `invoke` function in your Kotlin class, sometimes the IDE will not auto-import it 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.
 
- 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"]
 
- ----
 
- 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.
 
- 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.
 
 
  |