Spring Security 5迁移到Spring Security 6说明文档

Spring Security 5 迁移到 Spring Security 6/Spring Boot 3 说明文档

  1. 概述
    Spring Security 6 带来了几个重大变化,包括类的移除、废弃方法的移除以及新方法的引入。

从 Spring Security 5 迁移到 Spring Security 6 可以逐步进行,而不会破坏现有的代码库。此外,我们还可以使用第三方插件(如 OpenRewrite)来促进迁移到最新版本。

在本教程中,我们将学习如何将使用 Spring Security 5 的现有应用程序迁移到 Spring Security 6。我们将替换已废弃的方法并使用 lambda DSL 来简化配置。此外,我们还将利用 OpenRewrite 来加速迁移过程。

  1. Spring Security 和 Spring Boot 版本对应关系
    Spring Boot 基于 Spring 框架,Spring Boot 版本使用最新版本的 Spring 框架。Spring Boot 2 默认使用 Spring Security 5,而 Spring Boot 3 使用 Spring Security 6。

要在 Spring Boot 应用程序中使用 Spring Security,我们通常会在 pom.xml 中添加 spring-boot-starter-security 依赖。

然而,我们可以通过在 pom.xml 的 properties 部分指定所需版本来覆盖默认的 Spring Security 版本:

<properties>
    <spring-security.version>5.8.9</spring-security.version>
</properties>

在这里,我们指定在项目中使用 Spring Security 5.8.9,覆盖默认版本。

值得注意的是,我们也可以在 Spring Boot 2 中通过在 properties 部分覆盖默认版本来使用 Spring Security 6。

  1. Spring Security 6 的新特性
    Spring Security 6 引入了一些功能更新来提高安全性和健壮性。现在它至少需要 Java 17 版本并使用 jakarta 命名空间。

其中一个重大变化是移除了 WebSecurityConfigurerAdapter,转而采用基于组件的安全配置。

此外,移除了 authorizeRequests() 并用 authorizeHttpRequests() 来定义授权规则。

此外,它引入了诸如 requestMatcher() 和 securityMatcher() 等方法来替换 antMatcher() 和 mvcMatcher(),用于为请求资源配置安全策略。requestMatcher() 方法更加安全,因为它为请求配置选择适当的 RequestMatcher 实现。

其他废弃的方法如 cors() 和 csrf() 现在有了函数式风格的替代方案。

  1. 项目设置
    首先,让我们通过在 pom.xml 中添加 spring-boot-starter-web 和 spring-boot-starter-security 来引导一个 Spring Boot 2.7.5 项目:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.7.5</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.7.5</version>
</dependency>

spring-boot-starter-security 依赖使用 Spring Security 5。

接下来,让我们创建一个名为 WebSecurityConfig 的类:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}

在这里,我们用 @EnableWebSecurity 注解类来启动为 Web 请求配置安全的过程。此外,我们启用方法级授权。接下来,该类继承 WebSecurityConfigurerAdapter 类来提供各种安全配置方法。

此外,让我们定义一个内存用户进行身份验证:

@Override
void configure(AuthenticationManagerBuilder auth) throws Exception {
    UserDetails user = User.withDefaultPasswordEncoder()
      .username("Admin")
      .password("password")
      .roles("ADMIN")
      .build();
    auth.inMemoryAuthentication().withUser(user);
}

在上面的方法中,我们通过覆盖默认配置来创建一个内存用户。

接下来,让我们通过覆盖 configure(WebSecurity web) 方法来排除静态资源的安全控制:

@Override
void configure(WebSecurity web) {
    web.ignoring().antMatchers("/js/**", "/css/**");
}

最后,让我们通过覆盖 configure(HttpSecurity http) 方法来创建 HttpSecurity:

@Override
void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
      .antMatchers("/").permitAll()
      .anyRequest().authenticated()
      .and()
      .formLogin()
      .and()
      .httpBasic();
}

值得注意的是,这个设置展示了典型的 Spring Security 5 配置。在接下来的部分中,我们将把这段代码迁移到 Spring Security 6。

  1. 迁移项目到 Spring Security 6
    Spring 建议采用增量迁移方法来防止更新到 Spring Security 6 时破坏现有代码。在升级到 Spring Security 6 之前,我们可以先将 Spring Boot 应用程序升级到 Spring Security 5.8.5 并更新代码以使用新功能。迁移到 5.8.5 为我们准备了版本 6 中的预期变化。

在增量迁移过程中,我们的 IDE 可以警告我们已废弃的功能。这有助于增量更新过程。

为了简单起见,让我们直接将示例项目迁移到 Spring Security 6,通过将应用程序更新为使用 Spring Boot 版本 3.3.2。在应用程序使用 Spring Boot 版本 2 的情况下,我们可以在 properties 部分指定 Spring Security 6。

开始迁移过程,让我们修改 pom.xml 以使用最新的 Spring Boot 版本:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.3.2</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>3.3.2</version>
</dependency>

在初始设置中,我们使用 Spring Boot 2.7.5,它在底层使用 Spring Security 5。

值得注意的是,Spring Boot 3 的最低 Java 版本是 Java 17。

在后续的小节中,我们将重构现有代码以使用 Spring Security 6。

5.1. @Configuration 注解
在 Spring Security 6 之前,@Configuration 注解是 @EnableWebSecurity 的一部分,但通过最新更新,我们必须用 @Configuration 注解来注解我们的安全配置:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}

在这里,我们将 @Configuration 注解引入到现有代码库中,因为它不再属于 @EnableWebSecurity 注解的一部分。此外,该注解不再是 @EnableMethodSecurity、@EnableWebFluxSecurity 或 @EnableGlobalMethodSecurity 注解的一部分。

此外,@EnableGlobalMethodSecurity 被标记为废弃,将被 @EnableMethodSecurity 取代。默认情况下,它启用 Spring 的 pre-post 注解。因此,我们引入 @EnableMethodSecurity 来提供方法级别的授权

5.2. WebSecurityConfigurerAdapter
最新更新移除了 WebSecurityConfigurerAdapter 类并采用基于组件的配置:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
}

在这里,我们移除了 WebSecurityConfigurerAdapter,这消除了覆盖安全配置的方法。相反,我们可以注册一个安全配置的 bean。我们可以注册 WebSecurityCustomizer bean 来配置 Web 安全,SecurityFilterChain bean 来配置 HTTP 安全,InMemoryUserDetails bean 来注册自定义用户等等。

5.3. WebSecurityCustomizer Bean
让我们通过发布一个 WebSecurityCustomizer bean 来修改排除静态资源的方法:

@Bean
WebSecurityCustomizer webSecurityCustomizer() {
   return (web) -> web.ignoring().requestMatchers("/js/**", "/css/**");
}

WebSecurityCustomizer 接口替换了来自 WebSecurityConfigurerAdapter 接口的 configure(Websecurity web) 方法。

5.4. AuthenticationManager Bean
在前面的小节中,我们通过覆盖 WebSecurityConfigurerAdapter 的 configure(AuthenticationManagerBuilder auth) 创建了一个内存用户。

让我们通过注册 InMemoryUserDetailsManager bean 而不是重构身份验证凭据逻辑:

@Bean
InMemoryUserDetailsManager userDetailsService() {
    UserDetails user = User.withDefaultPasswordEncoder()
      .username("Admin")
      .password("admin")
      .roles("USER")
      .build();

    return new InMemoryUserDetailsManager(user);
}

在这里,我们定义了一个具有 USER 角色的内存用户来提供基于角色的授权。

5.5. HTTP 安全配置
在之前的 Spring Security 版本中,我们通过覆盖来自 WebSecurityConfigurer 类的 configure 方法来配置 HttpSecurity。由于它在最新版本中被移除,让我们注册 SecurityFilterChain bean 来进行 HTTP 安全配置:

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
      .authorizeHttpRequests(
          request -> request
            .requestMatchers("/").permitAll()
            .anyRequest().authenticated()
      )
      .formLogin(Customizer.withDefaults())
      .httpBasic(Customizer.withDefaults());
   return http.build();
}

在上面的代码中,我们将 authorizeRequest() 方法替换为 authorizeHttpRequests()。新方法使用 AuthorizationManager API,简化了重用和定制。

此外,它通过延迟身份验证查找来提高性能。身份验证查找仅在请求需要授权时发生。

当我们没有定制规则时,我们使用 Customizer.withDefaults() 方法来使用默认配置。

此外,我们使用 requestMatchers() 而不是 antMatcher() 或 mvcMatcher() 来保护资源。

5.6. 请求缓存
请求缓存帮助保存用户请求,当用户需要身份验证时并在他们成功身份验证后重定向用户到请求。在 Spring Security 6 之前,RequestCache 检查每个传入请求以查看是否有任何保存的请求要重定向到。这在每个 RequestCache 上读取 HttpSession。

然而,在 Spring Security 6 中,请求缓存仅检查请求是否包含特殊参数名 “continue”。这提高了性能并防止不必要的 HttpSession 读取。

  1. 使用 OpenRewrite
    此外,我们可以使用 OpenRewrite 等第三方工具将现有的 Spring Boot 应用程序迁移到 Spring Boot 3。由于 Spring Boot 3 使用 Spring Security 6,它也将安全配置迁移到版本 6。

要使用 OpenRewrite,我们可以将插件添加到 pom.xml:

<plugin>
    <groupId>org.openrewrite.maven</groupId>
    <artifactId>rewrite-maven-plugin</artifactId>
    <version>5.23.1</version>
    <configuration>
        <activeRecipes>
            <recipe>org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0</recipe>
        </activeRecipes>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.openrewrite.recipe</groupId>
            <artifactId>rewrite-spring</artifactId>
            <version>5.5.0</version>
        </dependency>
    </dependencies>
</plugin>

在这里,我们通过 recipe 属性指定升级到 Spring Boot 版本 3。OpenRewrite 有很多配方可供选择来升级 Java 项目。

最后,让我们运行迁移命令:

mvn rewrite:run

上面的命令将项目迁移到 Spring Boot 3,包括安全配置。然而,OpenRewrite 目前不使用 lambda DSL 来进行迁移的安全配置。当然,这在未来版本中可能会改变。

  1. 结论
    在本文中,我们看到了将使用 Spring Security 5 的现有代码库迁移到 Spring Security 6 的分步指南,包括替换已废弃的类和方法。此外,我们还看到了如何使用第三方插件来自动化迁移过程。

支持本文的代码可在 GitHub 上找到。一旦您以 Baeldung Pro 会员身份登录,开始在项目上学习和编码。

公告 - 图标
我刚刚宣布了新的 Learn Spring Security 课程,包括专注于 Spring Security 中新 OAuth2 堆栈的完整材料:

查看课程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码绘春秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值