WebFlux セキュリティ

Spring Security の WebFlux サポートは WebFilter に依存しており、Spring WebFlux および Spring WebFlux.Fn でも同じように機能します。いくつかのサンプルアプリケーションがコードを示しています。

最小限の WebFlux セキュリティ構成

次のリストは、最小限の WebFlux セキュリティ構成を示しています。

最小限の WebFlux セキュリティ構成
  • Java

  • Kotlin

@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)
    }
}

この構成は、フォームと HTTP の基本認証を提供し、任意のページにアクセスするために認証されたユーザーを要求する認可を設定し、デフォルトのログインページとデフォルトのログアウトページを設定し、セキュリティ関連の HTTP ヘッダーを設定し、CSRF 保護を追加します。

明示的な WebFlux セキュリティ構成

次のページは、最小限の WebFlux セキュリティ構成の明示的なバージョンを示しています。

明示的な WebFlux セキュリティ構成
  • Java

  • Kotlin

@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 { }
        }
    }
}
IDE がメソッドを常に自動インポートするとは限らず、コンパイルの問題が発生する可能性があるため、クラスで Kotlin DSL を有効にするには、必ず org.springframework.security.config.annotation.web.invoke 関数をインポートしてください。

この構成は、最小構成と同じものをすべて明示的に設定します。ここから、デフォルトをより簡単に変更できます。

 config/src/test/ ディレクトリの EnableWebFluxSecurity  [GitHub] (英語) を検索すると、単体テストで明示的な構成の例をさらに見つけることができます。

複数のチェーンサポート

複数の SecurityWebFilterChain インスタンスを構成して、RequestMatcher インスタンスごとに構成を分離できます。

例: /api で始まる URL の構成を分離できます:

  • Java

  • Kotlin

@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@Order を使用して SecurityWebFilterChain を構成し、Spring Security が最初に検討する必要がある SecurityWebFilterChain を指定します
2PathPatternParserServerWebExchangeMatcher を使用して、この SecurityWebFilterChain が /api/ で始まる URL パスにのみ適用されることを記述します
3/api/** エンドポイントに使用される認証メカニズムを指定します
4 他のすべての URL と一致するように、優先順位の低い SecurityWebFilterChain の別のインスタンスを作成します
5 アプリケーションの残りの部分で使用される認証メカニズムを指定します

Spring Security は、リクエストごとに 1 つの SecurityWebFilterChain@Bean を選択します。securityMatcher 定義の順番でリクエストに一致します。

この場合、URL パスが /api で始まる場合、Spring Security は apiHttpSecurity を使用することを意味します。URL が /api で始まらない場合、Spring Security はデフォルトで webHttpSecurity になります。これには、任意のリクエストに一致する暗黙の securityMatcher があります。