1. 概述

Spring Security 6 带来了重大变革,包括移除废弃类和方法、引入新特性等。从 Spring Security 5 迁移到 6 可以采用渐进式方式,避免破坏现有代码。此外,我们还能借助 OpenRewrite 这类第三方工具加速迁移过程。

本文将手把手教你如何将 Spring Security 5 应用迁移到 Spring Security 6,重点包括:

  • 替换所有废弃方法
  • 使用 Lambda DSL 简化配置
  • 通过 OpenRewrite 实现自动化迁移

⚠️ 注意:迁移前请确保你的代码库已做好版本兼容性准备。

2. Spring Security 与 Spring Boot 版本关系

Spring Boot 基于 Spring 框架,其版本直接决定了依赖的 Spring 框架版本:

  • Spring Boot 2 默认使用 Spring Security 5
  • Spring Boot 3 默认使用 Spring Security 6

在 Spring Boot 项目中,我们通常通过 pom.xml 添加 spring-boot-starter-security 依赖:

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

但可通过 properties 覆盖默认版本

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

这里强制指定使用 Spring Security 5.8.9,覆盖了 Spring Boot 的默认版本。

✅ 小技巧:你甚至可以在 Spring Boot 2 中使用 Spring Security 6,只需在 properties 中指定版本即可。

3. Spring Security 6 核心变化

Spring Security 6 引入多项重要改进:

  • 最低要求 Java 17
  • 使用 jakarta 命名空间
  • **彻底移除 WebSecurityConfigurerAdapter**,改用组件化配置
  • authorizeRequests()authorizeHttpRequests() 替代
  • **新增 requestMatcher()securityMatcher()**,替代 antMatcher()mvcMatcher()
  • cors()csrf() 等方法提供函数式风格替代方案

⚠️ 关键变化:requestMatcher() 会自动选择合适的 RequestMatcher 实现,比旧方法更安全可靠。

4. 项目初始化配置

先创建一个基于 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>

创建安全配置类 WebSecurityConfig

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

这里通过 @EnableWebSecurity 启用 Web 安全配置,@EnableGlobalMethodSecurity 开启方法级授权。

定义内存用户认证:

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

忽略静态资源安全检查:

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

配置 HTTP 安全规则:

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

这是典型的 Spring Security 5 配置,后续我们将把它迁移到 Spring Security 6。

5. 迁移到 Spring Security 6

Spring 官方推荐渐进式迁移策略: 先升级到 Spring Security 5.8.5,适配新特性后再升级到 6.x。IDE 会提示废弃方法,帮助逐步迁移。

为简化演示,我们直接升级到 Spring Boot 3.2.2(内置 Spring Security 6)。修改 pom.xml

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

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

⚠️ 注意:Spring Boot 3 要求 Java 17+。

接下来逐步重构代码:

5.1. @Configuration 注解变化

Spring Security 6 中 @Configuration 不再包含在 @EnableWebSecurity 中,需显式添加:

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

关键变化

  • 必须显式添加 @Configuration
  • @EnableGlobalMethodSecurity 被废弃,替换为 @EnableMethodSecurity
  • 新注解默认开启 @PreAuthorize/@PostAuthorize 支持

5.2. 移除 WebSecurityConfigurerAdapter

彻底移除 WebSecurityConfigurerAdapter,改用组件化配置:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
}

替代方案

  • 注册 WebSecurityCustomizer Bean 配置 Web 安全
  • 注册 SecurityFilterChain Bean 配置 HTTP 安全
  • 注册 InMemoryUserDetailsManager Bean 管理用户

5.3. WebSecurityCustomizer Bean

将静态资源忽略逻辑改为注册 WebSecurityCustomizer Bean:

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

✅ 优势:比旧版 configure(WebSecurity web) 更符合 Spring 6 的函数式风格。

5.4. 认证管理器 Bean

重构内存用户认证,改用 InMemoryUserDetailsManager Bean:

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

    return new InMemoryUserDetailsManager(user);
}

❌ 踩坑点:角色名称从 ADMIN 改为 USER(示例调整),实际迁移时请保持业务逻辑一致。

5.5. HTTP 安全配置

SecurityFilterChain Bean 替代旧的 configure(HttpSecurity 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();
}

核心改进

  • authorizeRequests()authorizeHttpRequests()
  • 使用 AuthorizationManager API 提升性能
  • 延迟认证查询(仅在需要授权时执行)
  • requestMatchers() 替代 antMatcher()/mvcMatcher()
  • Customizer.withDefaults() 应用默认配置

5.6. RequestCache 优化

Spring Security 6 对请求缓存机制做了性能优化:

  • 旧版:每次请求都检查 HttpSession 中是否有缓存请求
  • 新版:仅当请求包含 continue 参数时才检查缓存

这显著减少了不必要的 HttpSession 读取操作,提升整体性能。

6. 使用 OpenRewrite 自动迁移

OpenRewrite 可自动化迁移到 Spring Boot 3(内置 Spring Security 6)。添加插件:

<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>

执行迁移命令:

$ mvn rewrite:run

⚠️ 注意:当前版本不会自动转换为 Lambda DSL 风格,未来版本可能支持。

7. 总结

我们完整演示了从 Spring Security 5 到 6 的迁移过程,核心步骤包括:

  1. 升级 Spring Boot 到 3.x
  2. 移除 WebSecurityConfigurerAdapter
  3. 采用组件化 Bean 配置
  4. 使用新的 authorizeHttpRequests()requestMatchers()
  5. 利用 OpenRewrite 自动化基础迁移

迁移后代码更简洁、性能更优,且符合 Spring 6 的最佳实践。完整示例代码见 GitHub


原始标题:Migrate Application from Spring Security 5 to Spring Security 6/Spring Boot 3 | Baeldung