【问题标题】:java-jwt with public/private keys带有公钥/私钥的 java-jwt
【发布时间】:2016-10-09 21:04:27
【问题描述】:

Auth0 提供了两个 JWT 库,一个用于 Node:node-jsonwebtoken,一个用于 Java:java-jwt

我创建了私钥/公钥对,并在 Node 中成功使用node-jsonwebtoken

var key = fs.readFileSync('private.key');
var pem = fs.readFileSync('public.pem');

var header = {...};
var payload = {...};

header.algorithm = "RS256";
var message = jsonwebtoken.sign(payload, key, header);
var decoded = jsonwebtoken.verify(message, pem, {algorithm: "RS256"});

但我发现没有办法在 Java 中使用 java-jwt 做同样的事情。

谁有一个关于如何在 Java 中为 JWT 使用私钥/公钥的工作示例?

【问题讨论】:

  • 嗨 Predrag,我有同样的要求,我必须使用 java 创建带有私钥的签名令牌,并在节点 JS 中使用公钥验证令牌。我对如何加载私钥感到震惊(private key.pem) 文件并使用 RS256 算法创建签名令牌。如果您共享任何示例,那就太好了。

标签: java jwt auth0


【解决方案1】:

那个特定的库不支持它。但是您可以检查其他人的 Java。见这里:https://jwt.io/

【讨论】:

    【解决方案2】:

    我在 Java 中为 JWT 使用了以下代码。试试看。

    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    import io.jsonwebtoken.Claims;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    
    public class JWTJavaWithPublicPrivateKey {
    
        public static void main(String[] args) {
    
            System.out.println("generating keys");
            Map<String, Object> rsaKeys = null;
    
            try {
                rsaKeys = getRSAKeys();
            } catch (Exception e) {
    
                e.printStackTrace();
            }
            PublicKey publicKey = (PublicKey) rsaKeys.get("public");
            PrivateKey privateKey = (PrivateKey) rsaKeys.get("private");
    
            System.out.println("generated keys");
    
            String token = generateToken(privateKey);
            System.out.println("Generated Token:\n" + token);
    
            verifyToken(token, publicKey);
    
        }
    
        public static String generateToken(PrivateKey privateKey) {
            String token = null;
            try {
                Map<String, Object> claims = new HashMap<String, Object>();
    
                // put your information into claim
                claims.put("id", "xxx");
                claims.put("role", "user");
                claims.put("created", new Date());
    
                token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.RS512, privateKey).compact();
    
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return token;
        }
    
        // verify and get claims using public key
    
        private static Claims verifyToken(String token, PublicKey publicKey) {
            Claims claims;
            try {
                claims = Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token).getBody();
    
                System.out.println(claims.get("id"));
                System.out.println(claims.get("role"));
    
            } catch (Exception e) {
    
                claims = null;
            }
            return claims;
        }
    
        // Get RSA keys. Uses key size of 2048.
        private static Map<String, Object> getRSAKeys() throws Exception {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PrivateKey privateKey = keyPair.getPrivate();
            PublicKey publicKey = keyPair.getPublic();
            Map<String, Object> keys = new HashMap<String, Object>();
            keys.put("private", privateKey);
            keys.put("public", publicKey);
            return keys;
        }
    }
    
    Maven 依赖
    <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.6.0</version>
    </dependency>
    

    【讨论】:

    • 我们如何使用现有的密钥,(已经生成的密钥,存储在文件中)?
    • byte[] b1 = Base64.getDecoder().decode(privateKeyString); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b1); KeyFactory kf = KeyFactory.getInstance("RSA"); PrivateKey privateKey = kf.generatePrivate(spec);
    【解决方案3】:

    auth0 java-jwt 库的最新版本(自 3.0.0 起)支持 RSA and ECDSA 使用公钥/私钥对签署 JWT 令牌。

    使用 java-jwt 签署 JWT 的示例(基于 documentation)。

    import com.auth0.jwt.JWT;
    import com.auth0.jwt.JWTVerifier;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.auth0.jwt.exceptions.JWTCreationException;
    import com.auth0.jwt.exceptions.JWTVerificationException;
    import com.auth0.jwt.interfaces.DecodedJWT;
    
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.util.Map;
    
    class JwtPKSigningExample {
        public static void main(String[] args) throws Exception {
            Map<String, Object> keys = generateRSAKeys();
    
            String token = null;
            try {
                RSAPrivateKey privateKey = (RSAPrivateKey) keys.get("private");
                Algorithm algorithm = Algorithm.RSA256(null, privateKey);
                token = JWT.create()
                        .withIssuer("pk-signing-example")
                        .sign(algorithm);
            } catch (JWTCreationException x) {
                throw x;
            }
    
            try {
                RSAPublicKey publicKey = (RSAPublicKey) keys.get("public");
                Algorithm algorithm = Algorithm.RSA256(publicKey, null);
                JWTVerifier verifier = JWT.require(algorithm)
                        .withIssuer("pk-signing-example")
                        .build();
                DecodedJWT jwt = verifier.verify(token);
    
                System.out.println(jwt.getToken());
            } catch (JWTVerificationException x) {
                throw x;
            }
        }
    
        private static Map<String, Object> generateRSAKeys() throws Exception {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
    
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            return Map.of("private", keyPair.getPrivate(), "public", keyPair.getPublic());
        }
    }
    

    【讨论】:

      【解决方案4】:
          package com.java;
      
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.FileNotFoundException;
      import java.io.IOException;
      import java.io.InputStream;
      import java.security.KeyStore;
      import java.security.KeyStoreException;
      import java.security.NoSuchAlgorithmException;
      import java.security.PrivateKey;
      import java.security.UnrecoverableKeyException;
      import java.security.cert.CertificateException;
      import java.util.Enumeration;
      
      import org.jose4j.json.internal.json_simple.parser.ParseException;
      import org.jose4j.jwk.JsonWebKeySet;
      import org.jose4j.jws.AlgorithmIdentifiers;
      import org.jose4j.jws.JsonWebSignature;
      import org.jose4j.jwt.JwtClaims;
      import org.jose4j.jwt.MalformedClaimException;
      import org.jose4j.jwt.consumer.InvalidJwtException;
      import org.jose4j.jwt.consumer.JwtConsumer;
      import org.jose4j.jwt.consumer.JwtConsumerBuilder;
      import org.jose4j.keys.resolvers.JwksVerificationKeyResolver;
      import org.jose4j.keys.resolvers.VerificationKeyResolver;
      import org.jose4j.lang.JoseException;
      
      public class JWTSigningAndVerification {
      
          public static void main(String args[]) throws Exception {
      
              String jwt = generateJWT();
              validateJWTwithJWKS(jwt);
          }
      
          private static String generateJWT() throws FileNotFoundException, KeyStoreException, IOException,
                  NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, JoseException {
      
              JwtClaims jwt_claims = new JwtClaims();
      
              jwt_claims.setSubject("sub");
              jwt_claims.setIssuer("https://domain");
              jwt_claims.setIssuedAtToNow();
              jwt_claims.setExpirationTimeMinutesInTheFuture(1000000);
              jwt_claims.setGeneratedJwtId();
              jwt_claims.setClaim("sid", "sessionid");
              jwt_claims.setClaim("email", "test@mail.com");
              jwt_claims.setClaim("given_name", "first");
              jwt_claims.setClaim("family_name", "last");
      
              JsonWebSignature jws = new JsonWebSignature();
              jws.setPayload(jwt_claims.toJson());
              String KeyPassword = "p12-key-password";
              File file = new File("path-to-key.p12");
              InputStream stream = new FileInputStream(file);
              KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
              store.load(stream, KeyPassword.toCharArray());
              Enumeration e = store.aliases();
              String alias = (String) e.nextElement();
              PrivateKey key = (PrivateKey) store.getKey(alias, KeyPassword.toCharArray());
              jws.setKey(key);
              jws.setKeyIdHeaderValue("1");
              jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_PSS_USING_SHA512);
              jws.setHeader("typ", "JWT");
      
              String jwt = jws.getCompactSerialization();
              System.out.println(jwt);
      
              return jwt;
          }
      
          private static void validateJWTwithJWKS(String jwt) throws JoseException, FileNotFoundException, IOException,
                  ParseException, InvalidJwtException, MalformedClaimException {
      
              JsonWebKeySet jsonWebKeySet = new JsonWebKeySet("json-jwks-escaped");
              VerificationKeyResolver verificationKeyResolver = new JwksVerificationKeyResolver(jsonWebKeySet.getJsonWebKeys());
      
              JwtConsumer jwtConsumer = new JwtConsumerBuilder().setVerificationKeyResolver(verificationKeyResolver).build();
      
              JwtClaims claims = jwtConsumer.processToClaims(jwt);
              System.out.println("sub:- " + claims.getSubject());
          }
      
      }
      

      【讨论】:

      • 此代码块可用于签署 JWT 并使用 jose4j 库使用 JWKS 对其进行验证,如果您在使用它时遇到任何问题,请告诉我。
      猜你喜欢
      • 2016-10-14
      • 2020-06-17
      • 2018-12-14
      • 2017-01-27
      • 2016-12-01
      • 2020-07-05
      • 2013-04-06
      • 2019-06-30
      • 2017-05-11
      相关资源
      最近更新 更多