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

Spring Boot:微服务间通信时,另一微服务如何验证JWT Token

微服务B验证JWT Token的实现方案

要解决这个问题,核心是基于JWT的签名验证+Claims校验——微服务A生成Token时用密钥/私钥签名,微服务B必须用对应的密钥/公钥验证签名(确保Token未被篡改),同时校验过期时间、发行者等关键Claims。

下面分两种最常用的加密场景给出具体实现:

1. 对称加密(HS256/HS512)

这种方式下,微服务A和B共享同一个密钥,实现简单适合内部服务通信。

步骤与代码示例

首先在微服务B中引入JWT依赖(以JJWT库为例):

<!-- pom.xml -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

编写JWT验证工具类:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;

public class JwtValidator {
    // 注意:密钥要从配置文件读取,A和B必须用完全相同的值
    private static final String SECRET_KEY = "your-long-shared-secret-key-here-for-hs256";
    private static final SecretKey SIGNING_KEY = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());

    public static boolean validateToken(String token) {
        try {
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(SIGNING_KEY)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
            
            // 校验Token是否过期
            if (claims.getExpiration().before(new Date())) {
                return false;
            }
            // 可选:校验发行者,确保是微服务A签发的
            if (!"service-a".equals(claims.getIssuer())) {
                return false;
            }
            return true;
        } catch (Exception e) {
            // 签名无效、Token格式错误、过期等异常都会返回false
            return false;
        }
    }
}

在接口中使用验证逻辑:

@RestController
@RequestMapping("/api")
public class ServiceBController {
    @PostMapping("/process")
    public ResponseEntity<String> handleRequest(@RequestHeader("Authorization") String authHeader) {
        // 提取Token(假设格式为Bearer <token>)
        String token = authHeader.replace("Bearer ", "");
        if (JwtValidator.validateToken(token)) {
            // Token有效,处理业务逻辑
            return ResponseEntity.ok("Request processed successfully");
        } else {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid or expired token");
        }
    }
}

2. 非对称加密(RS256/RS512)

更安全的方案:微服务A用私钥签名Token,微服务B用公钥验证,无需共享敏感的私钥。

代码示例

将微服务A生成的公钥放在B的resources目录下(命名为public.key),编写验证工具类:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import java.io.InputStream;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;

public class JwtRsaValidator {
    private static PublicKey getPublicKey() throws Exception {
        InputStream inputStream = JwtRsaValidator.class.getClassLoader().getResourceAsStream("public.key");
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
        return cert.getPublicKey();
    }

    public static boolean validateToken(String token) {
        try {
            PublicKey publicKey = getPublicKey();
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(publicKey)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
            
            // 校验过期时间
            if (claims.getExpiration().before(new Date())) {
                return false;
            }
            // 校验发行者
            if (!"service-a".equals(claims.getIssuer())) {
                return false;
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

进阶优化:用Spring Security自动验证

如果不想手动在接口里处理,可以配置Spring Security的JWT过滤器,自动拦截请求并验证Token:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeHttpRequests(auth -> auth
                        .anyRequest().authenticated())
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(jwt -> jwt
                                .decoder(jwtDecoder())));
        return http.build();
    }

    @Bean
    public JwtDecoder jwtDecoder() {
        // 对称加密场景
        SecretKey secretKey = Keys.hmacShaKeyFor("your-shared-secret".getBytes());
        return NimbusJwtDecoder.withSecretKey(secretKey).build();
        
        // 非对称加密场景(替换上面的代码)
        // RSAPublicKey publicKey = ...; // 从文件或配置中心加载公钥
        // return NimbusJwtDecoder.withPublicKey(publicKey).build();
    }
}

谷歌相关学习资源

  • Google Cloud Identity Platform 官方JWT验证指南
  • Spring官方文档《Using JWT with Spring Security》章节
  • OWASP JWT Security Cheat Sheet

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:53:34