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

13

我有一个字符串形式的令牌,并下载了公钥证书并以以下方式创建了公钥。

但我不确定如何只依靠这些信息进行验证。

我找到了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();
4个回答

6

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

  1. Retrieve the algorithm the key has been signed with, for example:

    // Load your public key from a file
    final PublicKey ecdsa256PublicKey = getPublicKey(...);
    final Algorithm algorithm = Algorithm.ECDSA256((ECPublicKey) ecdsa256PublicKey, null);
    
  2. Verify its signature using the corresponding algorithm:

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

获取公钥的方法不明确。 - Gökhan Polat
在这里,加载公钥不是问题的一部分。如果您想了解如何加载公钥,请参阅此线程:https://dev59.com/v2gu5IYBdhLWcg3wUljt#19387517 - Florian Lopes

2

我做了类似这样的事情来验证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 进行注释以进行优化。


我已经尝试过了,程序卡在了“provider.get(decodedJWT.getKeyId())”这一行。 - i.am.jabi
你遇到了什么错误?你确定你传递的JWT或JWKs URL是正确的吗? - Abhishek Chandran
1
请问您能具体说明使用哪些库吗? - hariharan baskaran

0
一个使用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);
}

很明显,但请注意令牌和公钥是任意的。


1
你正在使用哪个软件包? - hariharan baskaran

-3
如果您询问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());
}

如需进一步阅读,您可以访问这里


1
apiKey是什么对象?如果我只有一个公钥证书文件,如何获取它的密钥? - Arham
apiKey 是 com.stormpath.sdk.api.ApiKey 对象,用于保存 apikey。String path = "resources/.stormpath/apiKey.properties";ApiKey apiKey = ApiKeys.builder().setFileLocation(path).build(); - Yogi
2
这并没有回答用户所问的问题。使用密钥验证是使用HS256(hmac),而使用公钥验证是RS256。 - jumper rbk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接