You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用本地JWKS文件验证Spring Boot资源服务的JWT令牌

使用本地JWKS文件验证JWT的Spring Boot优雅实现

1. 引入必要依赖

确保Spring Boot项目中引入OAuth2资源服务依赖:

Maven

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

Gradle

implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'

2. 自定义JWKS加载逻辑

Spring Security默认支持远程JWKS加载,我们需要自定义实现读取本地文件的JwkSetSource:

import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.source.JWKSetSource;
import com.nimbusds.jose.proc.SecurityContext;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

public class LocalJwkSetSource implements JWKSetSource<SecurityContext> {

    private final JWKSet jwkSet;

    public LocalJwkSetSource(String jwksFilePath) throws IOException {
        ClassPathResource resource = new ClassPathResource(jwksFilePath);
        try (InputStream is = resource.getInputStream()) {
            String jwksJson = new String(is.readAllBytes(), StandardCharsets.UTF_8);
            this.jwkSet = JWKSet.parse(jwksJson);
        }
    }

    @Override
    public JWKSet getJWKSet(SecurityContext context) {
        return jwkSet;
    }
}

3. 配置Spring Security过滤器链

在配置类中注入自定义JWKS源,构建JWT解码器,并设置资源服务安全规则:

import com.nimbusds.jose.jwk.source.JWKSetSource;
import com.nimbusds.jose.proc.SecurityContext;
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.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class ResourceServerSecurityConfig {

    @Bean
    public JWKSetSource<SecurityContext> localJwkSetSource() throws IOException {
        // 假设JWKS文件放在src/main/resources/jwks.json路径下
        return new LocalJwkSetSource("jwks.json");
    }

    @Bean
    public JwtDecoder jwtDecoder(JWKSetSource<SecurityContext> jwkSetSource) {
        return NimbusJwtDecoder.withJwkSetSource(jwkSetSource).build();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated() // 所有请求需验证JWT
            )
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt); // 启用JWT资源服务

        return http.build();
    }
}

4. 可选:配置JWT issuer校验

如果JWT包含issuer声明,在配置文件中添加对应校验规则:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://your-issuer-domain.com # 替换为实际issuer值

5. 核心逻辑说明

  • LocalJwkSetSource在项目启动时读取本地JWKS文件并解析为JWKSet对象,后续验证直接复用,避免重复IO操作
  • NimbusJwtDecoder会自动根据JWT的kid字段匹配JWKS中的公钥,完成签名验证、过期校验、issuer校验等核心逻辑
  • Spring Security自动拦截请求,提取Authorization头中的Bearer令牌,交给解码器验证,验证通过才放行请求

6. 测试验证

启动服务后,请求时携带Authorization: Bearer <your-jwt-token>头:

  • 令牌有效(签名正确、未过期、issuer匹配):正常访问接口
  • 令牌无效:返回401 Unauthorized

内容的提问来源于stack exchange,提问作者Vlada

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 01:55:19