# WebFlux 安全性

Spring Security 的 WebFlux 支持依赖于`WebFilter`，并且对 Spring WebFlux 和 Spring WebFlux.FN 的工作原理相同。你可以找到一些示例应用程序来演示下面的代码：

* Hello WebFlux[HelloWebFlux ](https://github.com/spring-projects/spring-security-samples/tree/5.6.x/reactive/webflux/java/hello-security)

* FN[HelloWebFluxFN ](https://github.com/spring-projects/spring-security-samples/tree/5.6.x/reactive/webflux-fn/hello-security)

* Hello WebFlux 方法[HelloWebFlux 方法](https://github.com/spring-projects/spring-security-samples/tree/5.6.x/reactive/webflux/java/method)

## 最小 WebFlux 安全配置

你可以在下面找到最小的 WebFlux 安全配置：

例 1。最小 WebFlux 安全配置

爪哇

```
@EnableWebFluxSecurity
public class HelloWebfluxSecurityConfig {

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

Kotlin

```
@EnableWebFluxSecurity
class HelloWebfluxSecurityConfig {

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

该配置提供表单和 HTTP 基本身份验证，设置授权以要求经过身份验证的用户访问任何页面，设置默认的登录页面和默认的注销页面，设置与安全相关的 HTTP 标题，CSRF 保护，等等。

## 显式 WebFlux 安全配置

你可以在下面找到最小 WebFlux 安全配置的显式版本：

例 2。显式 WebFlux 安全配置

爪哇

```
@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

```
@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 { }
        }
    }
}
```

这个配置显式地设置了与我们的最小配置相同的所有内容。从这里，你可以轻松地对默认值进行更改。

通过在`config/src/test/`目录中搜索[enableWebfluxsecurity]（https://github.com/ Spring-projects/ Spring-security/search？q=path%3aconfig%2fsrc%2ftest%2f+enableWebfluxsecurity），你可以在单元测试中找到更多显式配置的示例。

### 多链支撑

你可以通过`RequestMatcher`s 将多个`SecurityWebFilterChain`实例配置为单独的配置。

例如，可以为以`/api`开头的 URL 隔离配置，如下所示：

爪哇

```
@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

```
@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**|将`SecurityWebFilterChain`配置为`@Order`，以指定安全应该首先考虑哪个`SecurityWebFilterChain` Spring|
|-----|------------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|使用`PathPatternParserServerWebExchangeMatcher`声明此`SecurityWebFilterChain`将仅适用于以`/api/`开头的 URL 路径|
|**3**|指定将用于`/api/**`端点的身份验证机制|
|**4**|创建另一个优先级较低的`SecurityWebFilterChain`实例，以匹配所有其他 URL|
|**5**|指定将用于应用程序其余部分的身份验证机制|

Spring 安全性将为每个请求选择一个`SecurityWebFilterChain``@Bean`。它将按照`securityMatcher`定义的顺序匹配请求。

在这种情况下，这意味着如果 URL 路径以`/api`开始，那么 Spring Security 将使用`apiHttpSecurity`。如果 URL 不以`/api`开头，则 Spring Security 将默认为`webHttpSecurity`，其中隐含的`securityMatcher`与任何请求匹配。