如何手动校验JWT?Spring Boot手动解析JWKS公钥校验JWT
RSA类型JWK手动配置校验JWT实现方案
字段说明
你拿到的是标准RSA类型JSON Web Key结构,公钥不是单独存放在n字段,n和e两个字段共同组成完整RSA公钥:
n:RSA公钥模数,为Base64URL编码的二进制大整数,直接解码出现乱码是正常现象,本身就不是可读文本e:RSA公钥指数,同样为Base64URL编码的整数,示例里的AQAB对应常规RSA公钥指数65537- 其余辅助字段:
kty标识密钥类型为RSA,kid是密钥唯一ID,用来和JWT请求头里的kid字段做匹配,use标识密钥用途为签名校验,alg标识使用的签名算法。
Spring Boot实现代码
首先引入核心依赖,不需要额外引入Auth0的远程拉取组件:
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-jose</artifactId> </dependency>
核心校验逻辑如下,全程本地构造密钥,不需要网络请求拉取JWKS:
import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSVerifier; import com.nimbusds.jose.KeyUse; import com.nimbusds.jose.crypto.RSASSAVerifier; import com.nimbusds.jose.jwk.Base64URL; import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import java.security.interfaces.RSAPublicKey; import java.util.Date; public class ManualJwtValidator { // 替换为你获取到的完整参数值 private static final String MODULUS_N = "wEYJ85moXdpZT2vEW-jaeJrJnYqHumQpeakzyQJ0BJXDE3rZnxs17bLd_..."; private static final String EXPONENT_E = "AQAB"; private static final String KEY_ID = "testJWT"; // 替换为你实际使用的RSA签名算法,对应JWK里的alg字段 private static final JWSAlgorithm SIGN_ALG = JWSAlgorithm.RS256; public JWTClaimsSet verify(String jwtToken) throws Exception { // 本地构造RSA JWK对象,自动处理Base64URL解码逻辑 RSAKey rsaJwk = new RSAKey.Builder( new Base64URL(MODULUS_N), new Base64URL(EXPONENT_E) ) .keyID(KEY_ID) .algorithm(SIGN_ALG) .keyUse(KeyUse.SIGNATURE) .build(); RSAPublicKey publicKey = rsaJwk.toRSAPublicKey(); SignedJWT signedJwt = SignedJWT.parse(jwtToken); // 先校验密钥ID匹配,避免用错密钥 if (!KEY_ID.equals(signedJwt.getHeader().getKeyID())) { throw new IllegalArgumentException("JWT密钥ID不匹配"); } // 校验签名合法性 JWSVerifier verifier = new RSASSAVerifier(publicKey); if (!signedJwt.verify(verifier)) { throw new IllegalArgumentException("JWT签名校验失败"); } JWTClaimsSet claims = signedJwt.getJWTClaimsSet(); // 校验过期时间,可根据业务需求追加签发方、受众等字段校验 if (claims.getExpirationTime().before(new Date())) { throw new IllegalArgumentException("JWT已过期"); } return claims; } }
注意:不需要手动对
n和e字段做Base64解码处理,依赖库会自动完成解码、公钥结构构造的全流程。如果你的签名算法是RS384/RS512,直接替换SIGN_ALG对应的枚举值即可。
内容的提问来源于stack exchange,提问作者aatuc210
相关产品推荐
相关产品推荐

