相当于之前需要在后端服务中手动配置JWT公钥,麻烦不说还容易出错,现在有JWKS,可以通过 JWKS URI 自动拉取JWT公钥。
服务端收到客户端请求后,先解析JWT Header(头部)的kid,用kid去查询JWKS中的公钥,然后用公钥使用验证算法对Header(头部)和Payload(载荷)以及Signature(签名)进行验证,Verify(public_key, signature, header + payload),看该 Token 是否被篡改以及确实由持有私钥的认证服务器签发。
文章目录
深入理解 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
获取:
kidalg
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-rsajsonwebtoken
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技术社区



