对于最新的稳定版本,请使用 Spring Security 7.0.4spring-doc.cadn.net.cn

配置迁移

以下步骤涉及如何配置HttpSecurityWebSecurity及相关组件的更改。spring-doc.cadn.net.cn

使用 Lambda DSL

Spring Security 自从版本 5.2 起包含了 Lambda DSL,它允许使用 lambda 表达式配置 HTTP 安全。spring-doc.cadn.net.cn

您可能在Spring Security的文档或示例中见过这种配置风格。让我们看看HTTP安全的lambda配置与之前的配置风格有何不同。spring-doc.cadn.net.cn

使用 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。 这主要是出于以下几个原因:spring-doc.cadn.net.cn

  • 此前的方式,在不了解返回类型的情况下,不清楚是哪个对象在被配置。 嵌套层次越深,情况就越混乱。 即便是有经验的用户也会认为他们的配置实现了某个功能,实际上却做了另外的事情。spring-doc.cadn.net.cn

  • 一致性。 许多代码库在两种风格之间切换,导致了不一致的问题,使得理解配置变得困难,并且经常会导致配置错误。spring-doc.cadn.net.cn

Lambda DSL 配置技巧

当比较上面的两个示例时,您会注意到一些关键差异:spring-doc.cadn.net.cn

  • 在Lambda DSL中,无需使用.and()方法来链式配置选项。 调用lambda方法后,HttpSecurity实例将自动返回以进行进一步的配置。spring-doc.cadn.net.cn

  • Customizer.withDefaults() 启用了一个安全功能,该功能使用了 Spring Security 提供的默认设置。 这是一个 lambda 表达式 it → {} 的快捷方式。spring-doc.cadn.net.cn

WebFlux 安全

您也可以使用 lambda 表达式以类似的方式配置 WebFlux 安全性。 下面是一个使用 lambda 表达式进行配置的示例。spring-doc.cadn.net.cn

使用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 的目标

The Lambda DSL 用于实现以下目标:spring-doc.cadn.net.cn

使用.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 部分spring-doc.cadn.net.cn

使用dispatcherTypeMatchers而不是shouldFilterAllDispatcherTypes

如果允许错误派遣(ERROR dispatch),您可能在shouldFilterAllDispatcherTypes(false) DSL中使用了auhorizeHttpRequests方法:spring-doc.cadn.net.cn

http
    .authorizeHttpRequests((authorize) -> authorize
        .shouldFilterAllDispatcherTypes(false)
        // ...
    )
http {
    authorizeHttpRequests {
        shouldFilterAllDispatcherTypes = false
        // ...
    }
}

在准备切换到7时,请将此内容改为使用dispatcherTypeMatchers:spring-doc.cadn.net.cn

http
    .authorizHttpRequests((authorize) -> authorize
        .dispatcherTypeMatchers(DispatcherType.ERROR).permitAll()
        // ...
    )
http {
    authorizeHttpRequests {
        authorize(new DispatcherTypeRequestMatcher(DispatcherType.ERROR), permitAll())
    }
}