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 { }
        }
    }
}
請務必匯入 org.springframework.security.config.annotation.web.invoke 函式,以在您的類別中啟用 Kotlin DSL,因為 IDE 並非總是自動匯入該方法,這可能會導致編譯問題。

此組態明確地設定了與我們最小組態相同的所有內容。從這裡開始,您可以更輕鬆地變更預設值。

您可以在單元測試中找到更多明確組態的範例,方法是在 config/src/test/ 目錄中搜尋 EnableWebFluxSecurity

多個鏈結支援

您可以設定多個 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 設定具有 @OrderSecurityWebFilterChain,以指定 Spring Security 應優先考量的 SecurityWebFilterChain
2 使用 PathPatternParserServerWebExchangeMatcher 來聲明此 SecurityWebFilterChain 僅適用於以 /api/ 開頭的 URL 路徑
3 指定將用於 /api/** 端點的身份驗證機制
4 建立另一個具有較低優先順序的 SecurityWebFilterChain 實例,以比對所有其他 URL
5 指定將用於應用程式其餘部分的身份驗證機制

Spring Security 為每個請求選取一個 SecurityWebFilterChain @Bean。它依 securityMatcher 定義的順序比對請求。

在此情況下,這表示如果 URL 路徑以 /api 開頭,Spring Security 會使用 apiHttpSecurity。如果 URL 不以 /api 開頭,Spring Security 預設為 webHttpSecurity,後者具有隱含的 securityMatcher,可比對任何請求。