Dontla头像
关注

JWKS(JSON Web Key Set)介绍(为JWT 验证提供“动态可发现”的公钥集合)公钥分发、kid:Key ID密钥标识符、密钥轮换Key Rotation

相当于之前需要在后端服务中手动配置JWT公钥,麻烦不说还容易出错,现在有JWKS,可以通过 JWKS URI 自动拉取JWT公钥。

服务端收到客户端请求后,先解析JWT Header(头部)的kid,用kid去查询JWKS中的公钥,然后用公钥使用验证算法对Header(头部)和Payload(载荷)以及Signature(签名)进行验证,Verify(public_key, signature, header + payload),看该 Token 是否被篡改以及确实由持有私钥的认证服务器签发。

具体JWT结构,参见文章:网页token介绍(web token、web认证、web令牌、网页令牌)(JWT格式:JSON Web Token,头部Header、载荷Payload、签名Signature)JWT结构、共享密钥

深入理解 JWKS:JWT 公钥分发与密钥轮换的关键机制

在现代身份认证体系(如 OAuth2 / OIDC)中,JWT(JSON Web Token)已经成为事实标准。而当我们使用 非对称加密(如 RS256) 来签发 JWT 时,一个核心问题就出现了:

服务端如何安全、可靠地获取用于验证 JWT 的公钥?

这正是 JWKS(JSON Web Key Set) 要解决的问题。


一、什么是 JWKS?

JWKS(JSON Web Key Set) 是一个标准格式(JSON),用于表示一组公钥。

它通常通过一个 HTTP endpoint 暴露,例如:

https://your-idp.com/.well-known/jwks.json

返回示例:

{
  "keys": [
    {
      "kty": "RSA",
      "kid": "abc123",
      "use": "sig",
      "alg": "RS256",
      "n": "base64url-modulus",
      "e": "AQAB"
    }
  ]
}

二、JWKS 的核心作用

JWKS 的本质是:

为 JWT 验证提供“动态可发现”的公钥集合

它解决了以下问题:

1. 公钥分发

服务不需要手动配置公钥,而是:

  • 通过 JWKS URI 自动拉取
  • 解耦认证服务(IdP)和业务服务

2. 多 Key 支持(关键!)

JWT Header 中包含:

{
  "alg": "RS256",
  "kid": "abc123"
}

JWKS 中也有对应的 kid(Key ID 密钥标识符):

👉 服务端通过 kid 精确匹配对应公钥


3. 支持密钥轮换(Key Rotation)

这是 JWKS 最重要的价值之一。


三、为什么必须支持密钥轮换?

假设没有 JWKS:

  • 公钥写死在代码/配置中
  • 一旦私钥泄露 → 必须紧急更换
  • 所有服务都要同步更新公钥 ❌

而使用 JWKS:

  • IdP 发布新 key(新 kid)
  • JWKS endpoint 同时提供旧 key + 新 key
  • 客户端自动适配 ✅

👉 实现 平滑轮换(zero-downtime)


四、JWKS 工作流程

典型流程如下:

1️⃣ 客户端发起请求(携带 JWT)

Authorization: Bearer <JWT>

👉 JWT 是由认证服务器签发后,客户端(前端 / 调用方)持有并发送


2️⃣ 资源服务(Service / API)接收 JWT,解析 JWT Header

获取:

  • kid
  • alg

3️⃣ 获取 JWKS(如果缓存未命中)

GET https://idp/.well-known/jwks.json

4️⃣ 匹配 kid

JWT.kid == JWKS.keys[i].kid

5️⃣ 从JWKS构建公钥,并调用验证算法验证JWT中签名


五、最佳实践:JWKS 动态获取 + 缓存

约束:

JWT 公钥必须通过 JWKS URI 动态获取并缓存,支持密钥轮换

这是行业标准做法,实现时需要注意以下几点:


✅ 1. 必须做缓存(避免每次请求都拉)

推荐策略:

  • 内存缓存(如 LRU)
  • TTL:5 ~ 60 分钟
  • 或根据 HTTP Cache-Control

✅ 2. 缓存失效策略(非常关键)

推荐组合策略:

🔹 正常路径
  • 命中缓存 → 直接验证
🔹 kid 未命中(触发刷新)
if kid not found:
    refresh JWKS
    retry verification

✅ 3. 支持多 key 共存

JWKS 可能返回:

{
  "keys": [old_key, new_key]
}

👉 不要只缓存一个 key!


✅ 4. 异常保护(防止 DoS(拒绝服务攻击) Denial of Service Attack)

避免:

  • 每次 kid miss 都请求 JWKS ❌

建议:

  • 加限流 / 熔断
  • 使用“短时间内只刷新一次”策略

✅ 5. 使用成熟库(强烈建议)

不同语言常用库:

Node.js
  • jwks-rsa
  • jsonwebtoken
Python
  • PyJWT + jwcrypto
Java
  • Nimbus JOSE + JWT

六、JWKS 与 OIDC 的关系

在 OpenID Connect 中:

{
  "jwks_uri": "https://idp/.well-known/jwks.json"
}

👉 客户端通过 .well-known/openid-configuration 自动发现 JWKS 地址


七、常见坑(踩过的都懂)

❌ 1. 不校验 kid

👉 导致选错 key


❌ 2. 不缓存 JWKS

👉 性能灾难 + IdP 压力暴涨


❌ 3. 缓存不刷新

👉 key rotation 后全部验证失败


❌ 4. 只支持单 key

👉 无法平滑过渡


❌ 5. 忽略 alg 校验

👉 存在安全风险(算法混淆攻击)


八、总结

JWKS 可以理解为:

JWT 公钥的“动态配置中心”

它带来的核心价值:

  • ✅ 解耦认证系统与业务系统
  • ✅ 支持多 key + kid 精确匹配
  • ✅ 实现无缝密钥轮换
  • ✅ 提供标准化、自动化的公钥分发机制

九、一句话记住

JWT 负责“身份声明”,JWKS 负责“验证信任”。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/Dontla/article/details/160147096

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--