配置迁移

以下步骤与如何配置HttpSecurityWebSecurity和相关组件的更改有关。

使用 Lambda DSL

Lambda DSL 从 Spring Security 5.2 版本开始出现,它允许使用 lambda 表达式配置 HTTP 安全性。

您可能在 Spring Security 文档或示例中看到过这种配置风格。让我们看看使用 lambda 表达式配置 HTTP 安全性与之前的配置风格相比如何。

使用 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 DSL(如 Spring Integration 和 Spring Cloud Gateway)具有类似的配置风格。

对于自定义 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 部分