如何在 Nimbus JOSE + JWT 中验证令牌签名
Posted
技术标签:
【中文标题】如何在 Nimbus JOSE + JWT 中验证令牌签名【英文标题】:How to verify token signature in Nimbus JOSE + JWT 【发布时间】:2016-06-10 16:29:20 【问题描述】:每次使用Nimbus JOSE + JWT 请求资源时,我都有从服务器到客户端来回传输的令牌
创建 JWT 令牌的代码:
public class TokenProvider
String token = "";
public String getToken(String email)
try
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("RSA");
keyGenerator.initialize(1024);
KeyPair kp = keyGenerator.genKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate();
System.out.println("publicKey: " + publicKey);
System.out.println("privateKey: " + privateKey.toString());
JWSSigner signer = new RSASSASigner(privateKey);
JWTClaimsSet claimsSet = new JWTClaimsSet();
claimsSet.setSubject("RTH");
claimsSet.setCustomClaim("email", email);
claimsSet.setCustomClaim("role", "USER");
claimsSet.setIssuer("https://rth.com");
claimsSet.setExpirationTime(new Date(new Date().getTime() + 60 * 1000));
SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), claimsSet);
signedJWT.sign(signer);
token = signedJWT.serialize();
TokenSaverAndValidatorDAO tokenSaver = new TokenSaverAndValidatorDAO();
tokenSaver.saveTokenToDB(email, token);
signedJWT = SignedJWT.parse(token);
JWSVerifier verifier = new RSASSAVerifier(publicKey);
System.out.println("verifier: " + verifier);
System.out.println("verify method: " + signedJWT.verify(verifier));
assertTrue(signedJWT.verify(verifier));
assertEquals("RTH", signedJWT.getJWTClaimsSet().getSubject());
assertEquals("https://rth.com", signedJWT.getJWTClaimsSet().getIssuer());
assertTrue(new Date().before(signedJWT.getJWTClaimsSet().getExpirationTime()));
catch (JOSEException | ParseException | NoSuchAlgorithmException ex)
Logger.getLogger(TokenProvider.class.getName()).log(Level.SEVERE, null, ex);
return token;
到目前为止它工作正常,但问题是我如何验证从客户端收到的令牌签名?
从API 来看,只有一种方法看起来像是用于验证,但它只接受公钥 (RSAPublicKey
) 作为参数而不是令牌。
请帮助任何使用此库从事 JWT 工作的人。谢谢
【问题讨论】:
【参考方案1】:sample code 可以执行此操作,但您的问题中已准备好执行此操作的所有代码。
对于共享密钥:
JWSVerifier verifier = new MACVerifier(sharedKey.getBytes());
如果您使用的是 RSA 密钥对(如您的示例中所示),则只需提供公钥:
JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
然后要求它验证签名,注意如果签名无效会抛出异常:
boolean verifiedSignature = false;
try
JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
verifiedSignature = signedJWT.verify(verifier);
catch (JOSEException e)
System.err.println("Couldn't verify signature: " + e.getMessage());
检查令牌签名的完整方法可能如下所示:
public static boolean isSignatureValid(String token)
// Parse the JWS and verify its RSA signature
SignedJWT signedJWT;
try
signedJWT = SignedJWT.parse(token);
JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
return signedJWT.verify(verifier);
catch (ParseException | JOSEException e)
return false;
【讨论】:
以上是关于如何在 Nimbus JOSE + JWT 中验证令牌签名的主要内容,如果未能解决你的问题,请参考以下文章
在 nimbus-jose-jwt 中,lifespan 和 refreshTime 有啥区别?
嵌套 json JWT nimbus-jose -jwt 库
无法解析 nimbus-jose-jwt 库中的符号“加密”
编码实战2022年还在用jjwt操作jwt?,推荐你使用nimbus-jose-jwt,爽到飞起~
使用 nimbus-jose-jwt 时,当请求远程 url 进行缓存更新等时,我可以使用 RemoteJWKSet 找到(参见日志)