Spring Boot 3.0 如何配置基于 JWT 的无状态 API 鉴权流程?

文章导读
Spring Boot 3.0 项目中配置 JWT 无状态鉴权,核心是适应 Spring Security 6 的架构变化,使用 SecurityFilterChain Bean 替代已废弃的适配器类,并推荐优先使用 oauth2-resource-server starter 来简化校验逻辑。这适合前后端分离、需要无会话状态的 RESTful 接口场景。
📋 目录
  1. 1. 环境与依赖检查
  2. 2. 配置 application.yml
  3. 3. 编写 SecurityFilterChain 配置
  4. 4. 接口验证命令
  5. 5. 常见坑与排查
A A

Spring Boot 3.0 项目中配置 JWT 无状态鉴权,核心是适应 Spring Security 6 的架构变化,使用 SecurityFilterChain Bean 替代已废弃的适配器类,并推荐优先使用 oauth2-resource-server starter 来简化校验逻辑。这适合前后端分离、需要无会话状态的 RESTful 接口场景。

先说结论:配置关键在于依赖升级和 Security 配置类重构,不再继承旧版适配器。

  • 适合:前后端分离的 RESTful 项目
  • 先看:Java 版本是否满足 17 及以上
  • 建议:优先使用官方 Resource Server 支持而非手写过滤器
  • 注意:密钥配置需区分对称与非对称场景

1. 环境与依赖检查

Spring Boot 3.0 强制要求 Java 17 或更高版本。在 pom.xml 中确认 compiler 版本设置,并引入以下核心依赖:

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

2. 配置 application.yml

在配置文件中指定 JWT 校验规则。本地开发常用对称密钥(HS256),生产环境建议对接认证中心的 JWK Set URI。

Spring Boot 3.0 如何配置基于 JWT 的无状态 API 鉴权流程?

对称密钥配置示例:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          # 对称密钥,建议使用 Base64 编码字符串,长度需满足算法要求(如 HS256 至少 32 字符)
          secret-key: your-very-long-secret-key-base64-encoded
          # 或者指定算法(通常自动识别,必要时显式指定)
          # jws-algorithm: HS256

非对称密钥配置示例:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          # 指向认证服务器的公钥集合地址
          jwk-set-uri: https://auth-server.com/.well-known/jwks.json

3. 编写 SecurityFilterChain 配置

创建配置类,定义 SecurityFilterChain Bean。注意 Spring Boot 3 已全面迁移至 Jakarta EE,导入包名需为 jakarta.servlet 开头。同时需显式配置 CORS 和关闭 CSRF 以适配无状态 API。

Spring Boot 3.0 如何配置基于 JWT 的无状态 API 鉴权流程?
package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import java.util.Arrays;
import java.util.List;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            // 关闭 CSRF,因为是无状态 API
            .csrf(csrf -> csrf.disable())
            // 配置会话管理为无状态
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            // 配置 CORS
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            // 授权请求
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll() // 公开接口
                .anyRequest().authenticated() // 其他接口需认证
            )
            // 启用 OAuth2 Resource Server 支持 JWT
            .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(
                // 如果使用默认配置,Spring 会自动读取 yml 中的 secret-key 或 jwk-set-uri
                // 如需自定义解码器可在此注入,通常默认即可
                org.springframework.security.oauth2.jwt.JwtDecoders.fromIssuerLocation("http://localhost:8080") 
                // 注意:上面这行仅示例,实际使用默认配置时可直接写 .jwt(Customizer.withDefaults())
            )));
            
        // 简化写法(推荐):直接利用 yml 配置
        /*
        .oauth2ResourceServer(oauth2 -> oauth2.jwt(org.springframework.security.config.Customizer.withDefaults()));
        */
        
        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        return request -> {
            CorsConfiguration configuration = new CorsConfiguration();
            configuration.setAllowedOrigins(List.of("http://localhost:3000")); // 允许的前端域名
            configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
            configuration.setAllowedHeaders(List.of("*"));
            configuration.setAllowCredentials(true);
            return configuration;
        };
    }
}

4. 接口验证命令

启动项目后,使用 curl 命令验证鉴权流程是否生效。

步骤 1:访问受保护接口(不带 Token)

Spring Boot 3.0 如何配置基于 JWT 的无状态 API 鉴权流程?

预期返回 401 Unauthorized。

curl -v http://localhost:8080/api/user/profile

步骤 2:访问受保护接口(带 Token)

先生成一个有效的 JWT Token(本地测试可使用 jwt.io 生成,密钥需与 yml 中配置一致)。预期返回 200 OK 及业务数据。

curl -v -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." http://localhost:8080/api/user/profile

5. 常见坑与排查

  • 包名错误:代码中引用了 javax.servletjavax.annotation,编译会报错,需全部替换为 jakarta 开头。
  • 配置类遗留:旧项目中继承 WebSecurityConfigurerAdapter 的类必须删除或重构,否则应用无法启动。
  • CORS 拦截:无状态鉴权常跨域,需在 SecurityFilterChain 中显式配置 corsConfigurer,否则浏览器可能拦截请求导致前端拿不到 401 而是网络错误。
  • 密钥格式:对称密钥 secret-key 建议使用 Base64 编码,且长度需满足 JWT 算法安全要求(HS256 建议至少 256 位)。
  • Token 来源:Resource Server 只负责校验,不负责生成。测试时需确保 Token 是由可信的认证服务签发,或本地测试时手动生成符合配置的 Token。