從 Spring Security 5 遷移到 Spring Security 6/Spring Boot 3

Spring Security
Remote
0
09:33 AM · Nov 30 ,2025

1. 概述

Spring Security 6 帶來了諸多重大變更,包括移除類、廢棄方法,以及引入新方法。

從 Spring Security 5 遷移到 Spring Security 6 可以逐步進行,而不會破壞現有的代碼庫。 此外,我們還可以使用第三方插件(如 OpenRewrite)來協助遷移到最新版本。

在本教程中,我們將學習如何使用 Spring Security 5 將現有應用程序遷移到 Spring Security 6。 我們將替換廢棄的方法,並利用 lambda DSL 來簡化配置。 此外,我們還將利用 OpenRewrite 以加快遷移速度。

2. 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,我們始終將 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 中使用 Spring Security 6,方法是覆蓋默認版本,具體方法是在 properties 部分中。

3. Spring Security 6 中的新功能

Spring Security 6 引入了多個功能更新,以提高安全性及健壯性。它現在需要 Java 版本 17 或更高版本,並使用 jakarta 命名空間。

主要變更之一是棄用 WebSecurityConfigurerAdapter,改為基於組件的安全性配置。

此外,authorizeRequests() 已被移除並替換為 authorizeHttpRequests() 以定義授權規則。

更重要的是,它引入了 requestMatcher()securityMatcher() 方法來替換 antMatcher()mvcMatcher(),用於配置針對請求資源的安全性。 requestMatcher() 方法更安全,因為它會為請求配置選擇合適的 RequestMatcher 實現。

其他已棄用的方法,如 cors()csrf(),現在具有功能式替代方案。

4. 項目設置

為了開始,讓我們通過添加 spring-boot-starter-webspring-boot-starter-securitypom.xml


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

5. Migrating Project to 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 的情況下,我們可以將 Spring Security 6 指定到 properties 部分。

為了開始遷移過程,讓我們修改 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

在較早的章節中,我們通過覆蓋 configure(AuthenticationManagerBuilder auth) 方法來自 WebSecurityConfigurerAdapter 創建了一個內存用户。

讓我們通過註冊 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. RequestCache

請求緩存有助於保存用户請求,當需要身份驗證和將用户重定向到請求時,請求緩存保存用户請求。 在 Spring Security 6 之前,RequestCache 會在每個請求上檢查,以查看是否有任何保存的請求,以便將其重定向到該請求。 這會讀取 HttpSession 在每個 RequestCache 上。

然而,在 Spring Security 6 中,請求緩存僅檢查請求是否包含名為 "continue" 的特殊參數。 這提高了性能,並防止了不必要的讀取 HttpSession

6. 使用 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 進行遷移後的安全配置。當然,這很可能在未來的版本中發生變化。

7. 結論

在本文中,我們學習瞭如何使用 Spring Security 5 遷移現有代碼庫到 Spring Security 6 的逐步指南,通過替換已棄用的類和方法。此外,我們還了解了如何使用第三方插件來自動化遷移過程。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.