首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法解析Java中的JWK

无法解析Java中的JWK
EN

Stack Overflow用户
提问于 2021-08-25 16:49:15
回答 2查看 1.3K关注 0票数 3

我实现了一个rest授权服务器,它使用keyId包以JWK格式返回给定com.nimbusds:nimbus-jose-jwt:9.13的公钥。代码如下所示:

代码语言:javascript
复制
@RequestMapping(value = "/oauth2", produces = APPLICATION_JSON_VALUE)
public interface Rest {
...
    @GetMapping("/public-key/{keyId}")
    @Operation(summary = "Return the public key corresponding to the key id")
    JWK getPublicKey(@PathVariable String keyId);
}

public class RestController implements Rest {
.....
 public JWK getPublicKey(String keyId) {
         byte[] publicKeyBytes = ....
         RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
         JWK jwk = new RSAKey.Builder(publicKey)
                .keyID(keyId)
                .algorithm(new Algorithm(publicKey.getAlgorithm()))
                .keyUse(KeyUse.SIGNATURE)
                .build();
         return jwk;
    }
}

此代码以下列格式返回JWK键:

代码语言:javascript
复制
{
    "keyStore": null,
    "private": false,
    "publicExponent": {},
    "modulus": {},
    "firstPrimeFactor": null,
    "secondPrimeFactor": null,
    "firstFactorCRTExponent": null,
    "secondFactorCRTExponent": null,
    "firstCRTCoefficient": null,
    "otherPrimes": [],
    "requiredParams": {
        "e": "some-valid-exponent",
        "kty": "RSA",
        "n": "some-valid-modulus"
    },
    "privateExponent": null,
    "x509CertChain": null,
    "algorithm": {
        "name": "RSA",
        "requirement": null
    },
    "keyOperations": null,
    "keyID": "some-valid-key-id",
    "x509CertURL": null,
    "x509CertThumbprint": null,
    "x509CertSHA256Thumbprint": null,
    "parsedX509CertChain": null,
    "keyUse": {
        "value": "sig"
    },
    "keyType": {
        "value": "RSA",
        "requirement": "REQUIRED"
    }
}

在客户端(java),我尝试用以下代码解析jwk:

代码语言:javascript
复制
public JWK getPublicKey(String keyId) {
 String json = restTemplate.getForObject(publicUrl + "/oauth2/public-key/" + keyId, String.class);
        try {
            return JWK.parse(json);
        } catch (ParseException e) {
            log.error("Unable to parse JWK", e);
            return null;
        }
}

但是,由于parse抛出异常(Missing parameter "kty"),客户端无法解析密钥。我看到JWK.parse在主josn主体中需要一个kty键,而JWK的默认序列化则将kty键嵌入到requiredParams键中。当我尝试jwk.toString()时,我确实在主json主体中看到了kty键。

为什么本机JWK对象的序列化/反序列化不能以一种直接的方式工作?在不实现自定义jwt结构或序列化程序/反序列化器的情况下,修复这个问题的最佳方法是什么?

更新1:如果我们将返回类型从JWK更改为Map<String, Object>String并在客户端处理反序列化,则此代码将工作。但是,如果包本机为我们进行(反)序列化,情况会更好。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-01 16:30:16

答案是对那些面临这个问题的人使用String进行(反)序列化。为什么,你问?根据RFC,JWK是一个JSON格式的字符串。当nimbusds:nimbus-jose-jwt定义JWK对象时,任何返回有效JWK (或JWKSet)的API都可以假设它是一个字符串。

我还向这个包的开发人员提出了这个问题,他们建议使用StringMap<String, Object>进行(反)序列化。

票数 1
EN

Stack Overflow用户

发布于 2022-03-11 07:17:59

根据包这里的开发人员,应该通过端点公开JWK集,而不是单个JWK (参见https://connect2id.com/products/nimbus-jose-jwt/examples/validating-jwt-access-tokens):

发布一个由多个键组成的JWK集合(JSON数组),而不是在URL上只发布一个键,是为了方便顺利的键翻转。发布单个密钥后,切换到新键可能会导致客户端出现错误。 无论如何,如果您想保留一个键-每个URL,我建议您重写现有的com.nimbusds.jose.jwk.source.RemoteJWKSet,或者用com.nimbusds.jose.jwk.source.JWKSource实现您自己的单个JWK源(可能在需要时从RemoteJWKSet复制代码)。

更新:刚刚发现问题中JWKSet也存在相同的序列化问题

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68926941

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档