You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用jose4j实现JWT生成校验时RSA公私钥获取来源咨询

jose4j实现JWT时RSA公私钥获取问题

问题背景

  • 需求为对接指定API生成JWT令牌,采用jose4j依赖实现令牌生成、签名校验逻辑,在jwt.io调试示例令牌时发现签名环节需要配置公钥与私钥,相关签名配置界面参考:
    jwt.io签名配置参考截图
  • 参照官方文档编写的JWT生成代码如下:
public String createJWT() throws JoseException, MalformedClaimException {

        RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);;
        rsaJsonWebKey.setKeyId(keyId);

        JwtClaims claims = new JwtClaims();
        claims.setJwtId(keyId);
        claims.setIssuer(issuer);  // 令牌签发方标识
        claims.setAudience(audience); // 令牌接收方标识
        claims.setSubject(subject); // 令牌对应的主体身份
        claims.setExpirationTimeMinutesInTheFuture(60); // 令牌60分钟后过期
        claims.setGeneratedJwtId(); // 生成令牌唯一标识
        claims.setIssuedAtToNow();  // 设置令牌签发时间为当前时间
        claims.setNotBeforeMinutesInThePast(2); // 设置令牌2分钟前开始生效

        // 本次示例生成JWS格式签名令牌
        JsonWebSignature jws = new JsonWebSignature();
        jws.setPayload(claims.toJson());
        // 使用私钥完成签名
        jws.setKey(rsaJsonWebKey.getPrivateKey());
  • 现存初始疑问:
    • 不清楚签名所需私钥的获取渠道,也不确定私钥的具体存储形式
    • 现有存储username和password字段的keydata类,不确定这两个字段是否为签名需要的私钥
  • 编写的JWT校验逻辑代码如下:
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
                .setRequireExpirationTime() // 强制校验令牌过期时间
                .setAllowedClockSkewInSeconds(30) // 时间校验允许30秒时钟偏移
                .setRequireSubject() // 强制要求令牌携带subject字段
                .setExpectedIssuer("Issuer") // 校验令牌签发方
                .setExpectedAudience("Audience") // 校验令牌接收方
                .setVerificationKey(rsaJsonWebKey.getKey())// 使用公钥校验签名
                .setJwsAlgorithmConstraints( // 仅允许指定签名算法
                        AlgorithmConstraints.ConstraintType.PERMIT, AlgorithmIdentifiers.RSA_USING_SHA256) // 仅允许RS256算法
                .build();

上述代码中.setVerificationKey(rsaJsonWebKey.getKey())的作用是加载公钥完成签名合法性校验。

  • 核心咨询问题:JWT生成与校验流程中需要的RSA公私钥应当从哪里获取?是否需要向团队同事索要对应的密钥材料?

解答内容

  1. 首先纠正基础认知:keydata类里的username、password字段完全不是RSA公私钥。RSA非对称密钥是符合PKCS#1、PKCS#8等加密规范的专用密钥材料,和普通业务系统的账号密码字段没有任何关联。
  2. 你当前代码里RsaJwkGenerator.generateJwk(2048)的逻辑是每次调用方法都临时生成一对全新的RSA密钥,这种写法只能用于本地功能自测,绝对不能用到测试、生产环境——多实例部署、服务重启时生成的密钥不一致,会导致之前签发的所有令牌校验失败。
  3. 密钥获取渠道分场景处理:
    • 本地开发调试:可以自己用openssl、JDK自带keytool工具生成一对2048位及以上长度的RSA密钥,私钥存在本地安全目录用于签名,公钥配置到校验逻辑即可,自生成的调试密钥不要提交到公共代码仓库。
    • 测试/生产正式环境:必须找团队负责身份认证模块、密钥管理的同事索要对应环境的正规密钥材料:
      • 用于签名的RSA私钥是高度敏感信息,不会明文存在业务代码中,通常托管在专用密钥管理服务、服务器安全配置目录或者独立签名服务中,只有令牌签发服务有权限读取私钥
      • 用于验签的RSA公钥是可公开分发的材料,一般会通过配置中心、固定元数据接口或者统一对接文档同步给所有需要做令牌校验的服务方
  4. 索要密钥前先明确自己的服务职责:
    • 如果你的服务只需要校验上游传入的JWT,不需要对外签发JWT,你只需要申请对应签发方的公钥即可,不需要也不应该索要私钥
    • 如果你的服务本身就是JWT签发方,拿到私钥后不要硬编码在代码中,要通过环境变量、配置中心或者专用密钥SDK读取,避免私钥泄露
  5. 额外提醒:你当前校验逻辑里硬编码的"Issuer"、"Audience"是占位值,正式对接时要替换成团队约定的真实签发方、接收方标识,否则令牌校验会直接失败。

内容的提问来源于stack exchange,提问作者DiegoMG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 09:39:57