如何在 Java 中使用令牌和公钥验证 JWT 签名



我有一个字符串形式的令牌,我下载了公共证书并从中创建了一个公钥,如下所示。

但我不确定如何使用这么多信息进行验证。

我找到了C#和.NET的解决方案,但没有找到Java的解决方案。 请注意,我没有 jks 文件或私钥。

FileInputStream fin = new FileInputStream("d://public.crt");
CertificateFactory f = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate)f.generateCertificate(fin);
PublicKey pk = certificate.getPublicKey();

要使用 Auth0 库 (com.auth0:java-jwt( 验证 Java 中的 JWT:

  1. 检索密钥签名时使用的算法,例如:

    // Load your public key from a file
    final PublicKey ecdsa256PublicKey = getPublicKey(...);
    final Algorithm algorithm = Algorithm.ECDSA256((ECPublicKey) ecdsa256PublicKey, null);
    
  2. 使用相应的算法验证其签名:

    final DecodedJWT decodedJWT = JWT.decode("J.W.T[...]");
    // Will throw a SignatureVerificationException if the token's signature is invalid
    algorithm.verify(decodedJWT);
    

我做了这样的事情来验证 JWT

try {
DecodedJWT decodedJWT = JWT.decode(jwt); // your string
JwkProvider provider =  new JwkProviderBuilder(new URL("JWKS URL")).build();
Jwk jwk = provider.get(decodedJWT.getKeyId());
Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);
Verification verifier = JWT.require(algorithm);
verifier.build().verify(decodedJWT);
} catch (JWTVerificationException | JwkException | MalformedURLException e) {
// throw your exception
}

JwkProviderBuilder可能很昂贵,所以如果你正在使用 Spring,你可以把它提取为另一种方法,并用@PostConstruct对其进行注释以进行优化。

RSA密钥的工作示例如下所示:

/* Verification of JWT */
try {
String token = "some-token";
String publicKey = "some-key";

//Convert public key string to RSAPublicKey
byte[] publicKeyByteArr = Base64.getDecoder().decode(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyByteArr));
//If the token has an invalid signature, JWTVerificationException will raise.
Algorithm algorithm = Algorithm.RSA256(rsaPublicKey, null);
JWTVerifier verifier = JWT.require(algorithm)
//.withIssuer("auth0")
.build(); //Reusable verifier instance
DecodedJWT jwt = verifier.verify(token);
}catch(InvalidKeySpecException | NoSuchAlgorithmException | JWTVerificationException e) {
logger.info("JWT verification is failed");
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
}

这是显而易见的,但请注意,令牌和公钥是任意的。

如果你问到JSON WebToken,你可以按照下面的代码示例:

import javax.xml.bind.DatatypeConverter;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.Claims;
//Sample method to validate and read the JWT
private void parseJWT(String jwt) {
//This line will throw an exception if it is not a signed JWS (as expected)
Claims claims = Jwts.parser()         
.setSigningKey(DatatypeConverter.parseBase64Binary(apiKey.getSecret()))
.parseClaimsJws(jwt).getBody();
System.out.println("ID: " + claims.getId());
System.out.println("Subject: " + claims.getSubject());
System.out.println("Issuer: " + claims.getIssuer());
System.out.println("Expiration: " + claims.getExpiration());
}

如需进一步阅读,请访问 点击这里

最新更新