生成和签署 JSON Web 令牌时出错

Posted

技术标签:

【中文标题】生成和签署 JSON Web 令牌时出错【英文标题】:Error while Generate & Sign a JSON Web Token 【发布时间】:2021-12-24 20:54:47 【问题描述】:

我正在尝试创建 json Web 令牌并收到类似的错误

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:66)
Caused by: java.lang.IllegalArgumentException: RSA signatures be computed using a PrivateKey.Object of class [javax.crypto.spec.SecretKeySpec] must be an instance of interface java.security.PrivateKey

我正在使用私钥传递 base64 编码的 PEM 文件

LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBdXZmSEUrcVM4NlRsYmRFMVR0Mm55V3BPdnFCMjREcWZPc1Q2TFEzMFZFdFBBb0NxCno1T2EvMWwyTFhwZ2tQSG1TNnMxRUVXTUkrZXF3TWFGWHVKVHg1aVhYQk5id1BuSHNTZ2MrUWJnRW5rVzB3M1cKalRYWTF5blU3VmkzYjl2ck9WY2Urb1VkNTZuRXVidnc2ZFYzdXJsbmNMSTJ1a2FWbkVJaVVCRW1DYTMxQXdsUwpOSDRFQWVDUmYzUHhEWW52WnpJZFpBWlliajZsY1VOR1hRNTMyZTRCa1VwbWZwOUl5WDVsNzJ1ZU1RV3k1Z3NvCkR1ZnZYSlM0ZldCRURveFJxaFVNQWFTUHhhTzZQY0VOcDZGK3gxRWhtM0tKVytQU1FLVDJobVl3aUxPeHVrZGMKRHVXd0hNN3Z6YkZYU3lwbUpPWmNpMWw2b3o1T1hZemYvM2JWVHdJREFRQUJBb0lCQUZvbENQa1RTbExxbUN2QQppTUZEb1pnOUIwWmx1NnNVMkp6UFNBZmRDSVp6NE41R0J4VWFCOHRCNlBhNFlFTENQdFVROFA2dGFZb09Nb2ZMCnI1WTE3VXI0eVZGOWkrbVpCS3pudUVCaERqd1o0ZVZVY0xPWTJMbTAwNUswQ1kySExQeHlndDhxdTJac3Rnc1AKRUhMTmwzS1IzY3U2UVNUQ3ozT05kMW0vU3VXekE3UnE3S0hURHZpbnRGRDRRVUY5OXo0UXNycHVoK01lWWJ3ZwprRlhNUGcxWUl2RHJUUGpkNWZNY3EvaGNqR2NDbEVHUWZQL2h6U0M5bGtwcTZKa0lBM1p1Z1U4RDVtaXExWXFWCi9KeU5YZ2lndTd0c3l6UGNYTHM0MG40WkI2NmNCM0JrSDRMajV6YTI1anp4aDVHaldTS0RDb3NxVlowNGR2MHYKNG0wdEh2RUNnWUVBOGtKbzgzUHZkMk1tOXArZlpsZWRFaGdMRnp6cTM4V1dsRlhzV3E1T3gzQ2lkNTNOUWd0UQplVUJXdzRPUzRwOFJieHp1TkRSVDd3enFEWEIzUERIaWZveXVsWlkxcUhtcUxRY3VBelVHTmk4S2JkdHp2Q2hJCkNFVXdCMDhOeTMrMDdzOTRycGZHcUZ2cGFhb1RSRWluNWJZVWtKVkVHdW9rRW9oVHNQN1RpZVVDZ1lFQXhaS0oKMXJOM2hJRWRtditkODBJUFZ2Y2FVR05vSUxWd1hrZThIOUtlYUlEV1dqa2RFb2NtY09ZWDZJSnVINURjVGtCKwpzQlpwVUJmVzhiS3B0eFowM2hDWmhhZW03SUo5WGFrU2tiNDJhV1FQNWhmWXhFaktSYTcrN1I1VXM3ajMxNUxHCjVwTWNDQ01ybEpnTzRSZm9RUGIxMjNkbG43TEVLS0p2TVhUelh5TUNnWUVBeE56Q2ZGTlIzU3B0bHl2UFZGTU8KQ0k0Uk5Ta0RsQ1AwWVVZUmN2OENkWDlLQnZuc3VpYUhsb0I2QVJjQ1hiWDFiTjJObEU2UmhraHdTY3VDbVIvUQpkaFhNS1RLUEdBRUdFT0VzdXQ1ejFjUVVMWUdQWXU4NDJiK2ZiOUVGM01CQ1AyM0pHOWVxVDFXaEw0Uk5jOGUyCjZDdzJPZWVTR0d6OE16TWxEMGVFanlFQ2dZRUFwV3ZFTFJlbWdqTDQ3c1lISVoyMTZrS0tyYlFOZ3hWbk9Ba24KNGgwZXRMRHF5Qy81djRHWkZmNFJGb1BlWUYrUmxaTTZmNFRFT0dNOWZMRHltSEVjK0xFOVdVSzk2Rmg1VHVvNAp1ZjVnNEd6L1FzL0VsdE83U0F6MU5PT29WN0lQRVZlN1lXTGFuWldVNzUxQkdBWkVWK0J1aVlxMmM3Zmh0WVFMClJZVitIN0VDZ1lFQXZLTGhndkN5M3pHMWV0SStLT1p3ajRrUkxkSU5QQ0x0N2dHT1lGdnphRkdFMXYrZFBuUUkKYTEwWEJ5UmhqMWxwbUZxaFp6aHlIUldmVVpOc1lyN014T2E2NXZkd3lHWTZ2QzJpZWU2T04vUVhPajlmdzQ2eApxaUxoajNPTnNiaTJKQlovV0FSc09YQ09KZXVWTmNuZ29kdnBkeDd5UTJMZlVWcTl0ZTVHREswPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=

代码下方

//The JWT signature algorithm we will be using to sign the token
    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256;

    long nowMillis = System.currentTimeMillis();
    Date now = new Date(nowMillis);

    //We will sign our JWT with our ApiKey secret
    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcGdJQkFBS0NBUUVBMFZTLytaaDd0SWdtYVRKc0ZSMnJmNHVDanVOVEY0eWcwaXFSZ0dScmZsTEFtdkRUCkpSUm5JdmMvZkFBSFkyOEwrSk1RdHFvdE9wU1dnZ2hCSXZTaUw0bktleFQ2MHk4Y0VWU09zRmN0bGVVVkZxN3IKclRZREd3TGxFRzZrNDU5TmppMDh2dnVjdGkzbHRjSHo1b3ZzMUxGbXRkeUhITTdTczhEKzA5eEszZmkrU1ZUWApHQS9OMml2UEhGaHRwQlVCZnJNUWZUNm1Zckg5VXZsZFdlSlBZWENDYnI1TGwwc2IzaTdDV2FEc1I2NFlqTXlTClRid0U1ZVloWngwamJJTnNDQitRK0JqaDFZcklKMlV1T2xIZ2ozemJvVENnZ2pDWGsxbGdUaHJWdjJjenBTMmUKN0tFWmkrK3dwSmtvdHNUcTF4Q3RLU0wrMmg1NTFKbDRoOHJHQ3dJREFRQUJBb0lCQVFDKzZTWTBnb2EvdlRRYQoyT3VOem9Oc1RWWUM3dndIRERCWHZJNzZvNXNObUhja1YrS1pmS1FiVlpkR2hkZzNMVDJqdEt5WGkxaTRobTlGCnBEV1RwYnlNMG9RaUFKNUpJRHZlNmxsQUppSGpCUXhZcGFzM1MzMUZrenhKNGo3cmdZdi8wTzRIMS8yeWdPVngKQUxScVhNN2ZvL05paFArTW5HdTVtSmhQckNkempCSHVsS2IySUhQMEF5YXc1NFg3d0pHeVlIOXdQY2FOV2ZZdwowQjlocnFRK2VLSDBUS2dpcGRTdmVFbTR3SEVDUmxhUU95amc2ejIwQ3dsa3R2anRnc2JzVzFLZDVyc1Znb0tyClY4NjZreTltbFpoSkZoRHZrUHlOVUlXaW9QT3lGWDd1SHlQN1RzdGNRampYN3BqYlZYZTJ4U1pMU0toVFQxcnEKRzR6TzJyUUJBb0dCQVA4cG5Wblk0TVN6WUw3LzZRbmJYOERtZCt4eXlXd293VFd0d1F4TjZKNnV6ZzEzNHp3cApUdmlsak9BMlpwdy9iZ0UrY3VGa2piTXJQcFJoZVgrTFNpL1JBTGlHem1vNk5rNDFmd0J3OGRWOWs1TmFWWDRaCjN3UkdOR24rS1BWb2psbG9pMmQ2WWl0Q09nY1V4RVBVZDZaVUVoN2VlVjUybEpIVUlnZDBtR2NMQW9HQkFOSUUKb01ZU3M3NFZqYWhaUy8yVmlqZmV4L3BjL3cveWpFSUFVZUxDRjQrUEg4TFJkalY1bDV1YytPa1k4cHN5Z3BQNwo5azAxZUlJWXhzS0UwZEEzV1YrbUVZZU1CU2R6dXZZVDhwZEhBY291cFlESTdvbGtQZEpBdWpjTTY2eExtbWpKCnd0R3BQdkh3OEsvbWNDQjRkeVNrLzVSSERWc0ZKa0ZLRUt0ZjVuMEJBb0dCQUpwNm1rM3o5SmlCdFBmTnZVdC8KYWVoQ1g2WmlGRG9NTG5VT0hjc1NPOXdlSHBlZTFvN3N2MmZmNm5zdjFFMlNSVW94Z2FHZG5BQTJGU3dHRzJXeApjWmVqWkZsVEhCTEo3V2pLRUhxMjVtS0hKVnBYblZ5NzB2NG1kc01ZNGJrNXRMekNnMnVCZDMrVEY4aUR0Uk1QCnhlU0lEM1JxNG5Yak9xMVREY3NQdHRqakFvR0JBTE5vY3JOaUxKdjRLNUFoNEZHYlduekoyb21jd2VNc3J2WisKOFhURm0zenVwaEkxLzBaRlBlY1lYR1k4QXB2anRUcVhwbHRranpLTDJkYzN3VWllejhGdXkxREFvM0tGWWJSdgphL0FoSDMxSkJlY1RQdnF0WUVacE51cHFKaldFVEQ2eUJMUTRZV1lyRG1FbGVLbTBYd3MxeklNdGcxSTYvdWdOClRsb256VzBCQW9HQkFLS1FzNmluczJBbVl3UEtvVGJEOUlza3NtdElZOUNacG1pTVVCRkZBMld6dFBSNUVhUzAKYTgrb2JaRXNRa3dZZzVSQTZUS0FzZUlJem1yZUE3RkVUd21nMmNmZW1wOW81bXJETy85bkk4blFYU24xeEdZWApmN2VBMlh6bHcvN3lrMENaekYwMnA4b3dSMzc3cFcrWkp4RkgraHJPUnh4dWFWcnJob3I5VVN4TwotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=");
    Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

    //Let's set the JWT Claims
    JwtBuilder builder = Jwts.builder().setId("ID")
            .setIssuedAt(now)
            .setSubject("subject")
            .setIssuer("issuer")
            .signWith(signatureAlgorithm, signingKey);


    //Builds the JWT and serializes it to a compact, URL-safe string
    System.out.println("-------------------------------------"+builder.compact());

【问题讨论】:

【参考方案1】:

您使用了错误的密钥 SecretKeySpec。应该是 PrivateKey。

例如:

Jwts.builder().signWith(SignatureAlgorithm.RS256, getPrivateKey("RSA",keyContent))
        .setAudience("audien")
        .setIssuer("issuer")
        .setSubject("subject")
        .setExpiration(expiredDate).compact();

根据要求,我在这里添加了 loadPrivateKey 函数。

public static PrivateKey getPrivateKey(String algorithm, String keyContent)
      throws Exception
    try 
      byte[] encoded = decodeBase64(keyContent);
      KeyFactory kf = KeyFactory.getInstance(algorithm);
      PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
      PrivateKey privateKey = kf.generatePrivate(keySpec);
      return privateKey;
     catch (Exception ex) 
      //log error
      throw ex;
    

【讨论】:

谢谢,你能给我更多关于 getPrivateKey(privateKeyLocator) 的详细信息 我添加了将 keyContent 转换为 PrivateKey 的代码。希望你清楚。 好的,谢谢!请提供代码! 已添加答案,刷新页面即可。 现在我得到一些其他错误,例如: 引起:java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format

以上是关于生成和签署 JSON Web 令牌时出错的主要内容,如果未能解决你的问题,请参考以下文章

NPM 解析 Json 时出错,意外的令牌

尝试使用 .NET JWT 库生成令牌时出错

Firebase AppCheck iOS 在生成 appcheck 令牌错误代码 0 时出错

为可编辑的Power BI Embedded仪表板生成嵌入令牌时出错

Fabric 插件:存档打包错误:-6 重新签署应用程序以进行分发时出错

url解码和发布数据后出错