Configuration Migrations

以下步骤涉及如何配置 HttpSecurityWebSecurity 和相关组件的变化。

The following steps relate to changes around how to configure HttpSecurity, WebSecurity and related components.

Use the Lambda DSL

自 5.2 版起,Spring Security 中包含 Lambda DSL,它允许使用 lambda 来配置 HTTP 安全。

The Lambda DSL is present in Spring Security since version 5.2, and it allows HTTP security to be configured using lambdas.

你可能在 Spring Security 文档或示例中看到过这种配置样式。让我们来看看 HTTP 安全的 lambda 配置与之前的配置样式相比有何不同。

You may have seen this style of configuration in the Spring Security documentation or samples. Let us take a look at how a lambda configuration of HTTP security compares to the previous configuration style.

Configuration using lambdas
@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();
    }
}
Equivalent configuration without using lambdas
@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 中,之前的配置样式将无效,Spring Security 7 要求使用 Lambda DSL。这样做主要有几个原因:

The Lambda DSL is the preferred way to configure Spring Security, the prior configuration style will not be valid in Spring Security 7 where the usage of the Lambda DSL will be required. This has been done mainly for a couple of reasons:

  • 之前的方式不够明确,不知道返回类型是什么,所以不知道正在配置哪个对象。嵌套得越深,就越令人困惑。即使是经验丰富的用户也会认为他们的配置做了一件事,但实际上却做了另一件事。

  • The previous way it was not clear what object was getting configured without knowing what the return type was. The deeper the nesting the more confusing it became. Even experienced users would think that their configuration was doing one thing when in fact, it was doing something else.

  • 一致性。很多代码库在这两种风格之间切换,导致了不一致,从而难以理解配置,而且还经常导致错误配置。

  • Consistency. Many code bases switched between the two styles which caused inconsistencies that made understanding the configuration difficult and often led to misconfigurations.

Lambda DSL Configuration Tips

比较上述两个示例时,你会注意到一些关键差异:

When comparing the two samples above, you will notice some key differences:

  • 在 Lambda DSL 中,无需使用 .and() 方法来链接配置选项。在调用 lambda 方法之后,会自动返回 HttpSecurity 实例以便进行进一步的配置。

  • In the Lambda DSL there is no need to chain configuration options using the .and() method. The HttpSecurity instance is automatically returned for further configuration after the call to the lambda method.

  • Customizer.withDefaults() 使用 Spring Security 提供的默认值来启用安全功能。这是一个对 lambda 表达式 it → {} 的快捷方式。

  • Customizer.withDefaults() enables a security feature using the defaults provided by Spring Security. This is a shortcut for the lambda expression it → {}.

WebFlux Security

你还可以类似地使用 lambda 配置 WebFlux 安全。以下是使用 lambda 的示例配置。

You may also configure WebFlux security using lambdas in a similar manner. Below is an example configuration using lambdas.

WebFlux configuration using lambdas
@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();
    }

}

Goals of the Lambda DSL

Lambda DSL 的创建是为了实现以下目标:

The Lambda DSL was created to accomplish to following goals:

  • 自动缩进使配置更易读。

  • Automatic indentation makes the configuration more readable.

  • 无需使用 `.and()`链接配置选项

  • There is no need to chain configuration options using .and()

  • Spring Security DSL 的配置风格与其他 Spring DSL(例如 Spring Integration 和 Spring Cloud Gateway)类似。

  • The Spring Security DSL has a similar configuration style to other Spring DSLs such as Spring Integration and Spring Cloud Gateway.

Use .with() instead of .apply() for Custom DSLs

在 6.2 之前的版本中,如果您有一个 custom DSL,您需要使用 HttpSecurity#apply(…​) 方法将其应用到 HttpSecurity。但是,从版本 6.2 开始,此方法已弃用,并且将在 7.0 中删除,因为一旦删除 .and(),就不再可能使用 .and() 来链接配置(参见 [role="bare"][role="bare"]https://github.com/spring-projects/spring-security/issues/13067)。相反,建议使用新的 .with(…​) 方法。有关如何使用 .with(…​) 的详细信息,请参阅 Custom DSLs section

In versions prior to 6.2, if you had a custom DSL, you would apply it to the HttpSecurity using the HttpSecurity#apply(…​) method. However, starting from version 6.2, this method is deprecated and will be removed in 7.0 because it will no longer be possible to chain configurations using .and() once .and() is removed (see [role="bare"]https://github.com/spring-projects/spring-security/issues/13067). Instead, it is recommended to use the new .with(…​) method. For more information about how to use .with(…​) please refer to the Custom DSLs section.