配置遷移

以下步驟涉及如何配置 HttpSecurityWebSecurity 及相關元件的變化。

使用 Lambda DSL

Lambda DSL 自 Spring Security 5.2 版本起就已存在,它允許使用 lambda 表示式來配置 HTTP 安全。

您可能在 Spring Security 文件或示例中見過這種配置風格。讓我們來看看 HTTP 安全的 lambda 配置與之前的配置風格有何不同。

使用 lambda 的配置
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/blog/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(formLogin -> formLogin
                .loginPage("/login")
                .permitAll()
            )
            .rememberMe(Customizer.withDefaults());

        return http.build();
    }
}
不使用 lambda 的等效配置
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests()
                .requestMatchers("/blog/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .rememberMe();

        return http.build();
    }
}

Lambda DSL 是配置 Spring Security 的首選方式,之前的配置風格將在 Spring Security 7 中失效,屆時將強制要求使用 Lambda DSL。這樣做主要是出於幾個原因:

  • 之前的方式如果不瞭解返回型別,就不清楚正在配置哪個物件。巢狀越深,就越容易混淆。即使是經驗豐富的使用者也會認為他們的配置在做一件事,而實際上卻在做另一件事。

  • 一致性。許多程式碼庫在這兩種風格之間切換,導致不一致,使得理解配置變得困難,並經常導致配置錯誤。

Lambda DSL 配置技巧

在比較上面的兩個示例時,您會注意到一些關鍵區別

  • 在 Lambda DSL 中,無需使用 .and() 方法鏈式呼叫配置選項。呼叫 lambda 方法後,HttpSecurity 例項會自動返回以進行進一步配置。

  • Customizer.withDefaults() 使用 Spring Security 提供的預設設定啟用安全功能。這是 lambda 表示式 it → {} 的快捷方式。

WebFlux 安全

您也可以以類似方式使用 lambda 配置 WebFlux 安全。以下是使用 lambda 的配置示例。

使用 lambda 的 WebFlux 配置
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
            .authorizeExchange(exchanges -> exchanges
                .pathMatchers("/blog/**").permitAll()
                .anyExchange().authenticated()
            )
            .httpBasic(Customizer.withDefaults())
            .formLogin(formLogin -> formLogin
                .loginPage("/login")
            );

        return http.build();
    }

}

Lambda DSL 的目標

建立 Lambda DSL 旨在實現以下目標

  • 自動縮排使配置更具可讀性。

  • 無需使用 .and() 鏈式呼叫配置選項

  • Spring Security DSL 與 Spring Integration 和 Spring Cloud Gateway 等其他 Spring DSL 具有類似的配置風格。

自定義 DSL 使用 .with() 代替 .apply()

在 6.2 版本之前,如果您有自定義 DSL,您會使用 HttpSecurity#apply(…​) 方法將其應用到 HttpSecurity。然而,從 6.2 版本開始,此方法已被棄用,並將在 7.0 版本中移除,因為一旦 .and() 被移除,將無法再使用 .and() 鏈式呼叫配置(參見github.com/spring-projects/spring-security/issues/13067)。因此,建議使用新的 .with(…​) 方法。有關如何使用 .with(…​) 的更多資訊,請參閱自定義 DSL 部分