网络安全认证鉴权后端【免费下载链接】joseJWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes项目地址https://gitcode.com/gh_mirrors/jo/jose点击查看免费下载本篇技术指南围绕 jose 仓库的jwks/local模块展开系统讲解如何使用createLocalJWKSet从一份本地或以其他方式可得的 JSON Web Key SetJWKS中解析出用于 JWS 签名验证的公钥并深入剖析其密钥选择规则、缓存机制、错误处理与源码实现。读完本文你将掌握本地 JWKS 的校验模型能够直接将其接入jwtVerify等验证函数并懂得如何优雅处理多密钥命中与失败场景。模块概览什么是 jwks/local在 JOSE 生态中验证 JWS进而验证 JWT通常需要先拿到签名者的公钥。公钥可以由调用方逐个传入如importSPKI、importJWK的结果也可以集中存放在一份 JSON Web Key Set 中让验证方按 JWS 头部的alg与kid自动挑选。jose 提供了两种基于 JWKS 的密钥解析器jwks/localJWKS 数据在本地可用例如硬编码在配置中、来自数据库或环境变量无需网络请求jwks/remoteJWKS 从远程 HTTP 端点获取并带有缓存与超时控制见 docs/jwks/remote/README.md。本模块的入口文档 docs/jwks/local/README.md 将其定位为 Verification using a JSON Web Key Set (JWKS) available locally对外暴露两样东西函数createLocalJWKSet接收一份 JWKS 对象返回一个密钥解析函数接口LocalJWKSet描述该解析函数的类型形状。该函数既可以从主模块jose命名导出也可以从子路径jose/jwks/local导入package.json 的exports字段中可见./jwks/local的映射见 package.json适合按需引入、减小打包体积。createLocalJWKSet 快速上手createLocalJWKSet的签名非常简单createLocalJWKSet(jwks: JSONWebKeySet): LocalJWKSet。传入的jwks必须是符合 JSONWebKeySet 形状的对象即{ keys: JWK[] }。以下是官方文档给出的完整示例见 createLocalJWKSet 文档使用两个公钥——一个 RSAPS256一个 EC P-256ES256const JWKS jose.createLocalJWKSet({ keys: [ { kty: RSA, e: AQAB, n: 12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ, alg: PS256, }, { crv: P-256, kty: EC, x: ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw, y: _LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo, alg: ES256, }, ], }) const { payload, protectedHeader } await jose.jwtVerify(jwt, JWKS, { issuer: urn:example:issuer, audience: urn:example:audience, }) console.log(protectedHeader) console.log(payload)要点说明解析函数可以直接作为jwtVerify的getKey参数传入jose 的其他消费函数compactVerify、flattenedVerify、generalVerify等同样接受该函数传入的jwt头部应包含alg如ES256与kid解析器据此在keys中挑选对应的公钥在 Node.js 中使用时需先import * as jose from jose在浏览器、Deno、Bun 等 Web-interoperable 运行时中同样可用项目定位即覆盖这些运行时见 package.json。LocalJWKSet 接口形态返回的解析函数类型为LocalJWKSet其可调用签名为LocalJWKSet( protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput, ): PromiseCryptoKeyprotectedHeaderJWS 受保护头部JWSHeaderParameterstoken扁平化 JWS 输入FlattenedJWSInput其header中的参数会与protectedHeader合并用于匹配返回PromiseCryptoKey即通过 WebCryptoimportKey得到的公钥对象。此外该函数还挂载了一个属性jwks()返回创建时那份 JWKS 的结构化克隆structured clone。这一点在源码中有明确实现createLocalJWKSet在返回的解析函数上用Object.defineProperty安装了jwks属性其值为() structuredClone(snapshot)见 src/jwks/local.ts。测试 test/jwks/local.test.ts 验证了克隆行为set.jwks()返回的对象既不等同于原始jwks也不等同于每次调用返回的新对象但内容深度相等——这意味着调用方可以安全地读取/修改该副本而不会污染内部状态。密钥选择规则核心机制这是createLocalJWKSet最重要的行为。官方文档的描述是它使用 JWS 头部的alg确定 JWK 应有的kty再用kid与头部kid匹配同时尊重 JWK 上的use与key_ops。源码中的isUsableJWK见 src/jwks/local.ts将其精确实现为以下全部条件JWK 字段条件ext可导出未定义或必须是布尔值key_ops密钥操作未定义或必须是不重复字符串数组且包含verifykty密钥类型必须包含在alg对应的允许类型列表中kid密钥 ID若头部提供了kid则必须为字符串且与 JWK 的kid相等头部未提供时不作为限制alg算法未定义时要求kty ! AKP定义时则必须与头部alg完全相等use公钥用途未定义或必须为sigcrv曲线未定义或必须与alg对应的期望曲线一致关于alg与kty的映射来源是 src/lib/jws_algorithms.ts 中的 JWS 算法表对称 HMAC 算法HS256/HS384/HS512对应kty: oct且被标记为secretRSA 算法RS256/384/512、PS256/384/512后者带saltLength对应kty: RSA并要求 RSA 密钥至少 2048 位minRsaBits: 2048ECDSA 算法ES256/384/512对应kty: EC并绑定具体曲线P-256/P-384/P-521EdDSA/Ed25519对应kty: OKP、crv: Ed25519后量子签名ML-DSA-44/65/87对应kty: AKP。由于createLocalJWKSet的用途是验证签名isUsableJWK会拒绝secret性质的算法即HS*对称密钥源码中相应分支直接抛出JOSENotSupported(Unsupported alg value for a JSON Web Key Set)见 src/jwks/local.ts。同时官方文档也以 [!NOTE]明确指出该函数只用于解析验证签名的公钥不适用于公钥加密JWE场景。头部参数合并createLocalJWKSet的解析函数首先执行const { alg, kid } { ...protectedHeader, ...token?.header }见 src/jwks/local.ts。这意味着token.header未受保护/额外头部中的参数会覆盖protectedHeader中的同名参数。若alg不是字符串则直接按不支持的算法处理。输入校验构造时即拒绝畸形 JWKScreateLocalJWKSet在创建阶段就对输入做严格校验而不是等到验证时才发现问题。源码首先尝试structuredClone(jwks)得到内部快照然后调用isJwkSet校验见 src/lib/type_checks.ts输入必须是普通对象或__proto__为 null 的对象keys必须是数组每个元素必须是对象。不满足任一条件即抛出JWKSInvalid错误码ERR_JWKS_INVALID。测试 test/jwks/local.test.ts 覆盖了null、{}、{ keys: null }、{ keys: [0] }、稀疏数组等各种畸形输入全部断言抛出ERR_JWKS_INVALID。校验失败发生在构造函数内部所以createLocalJWKSet(f)是同步抛出错误的调用时无需await或try/catch异步包装。缓存机制按算法缓存导入的公钥每次解析都会调用 WebCrypto 的importKey这是相对昂贵的操作。为了复用createLocalJWKSet内部维护了一个WeakMapJWK, Cache其中Cache是以alg为键、CryptoKey为值的对象见 src/jwks/local.ts。importWithAlgCache见 src/jwks/local.ts的逻辑是以原始 JWK 对象为键查缓存未命中则初始化一个空缓存对象若该 JWK 在该alg下尚未导入过公钥则调用jwkToKey导入导入结果会校验key.type ! public若是私钥则抛出JWKSInvalid(JSON Web Key Set members must be public keys)导入成功后将公钥写入缓存并返回。使用WeakMap意味着缓存不会阻止 JWK 对象被垃圾回收且键是对象引用而非序列化值——内部快照中的每个 JWK 对象在整个生命周期内保持引用稳定缓存才能命中。底层jwkToKey见 src/lib/jwk_to_key.ts在导入前还会删除use字段AKP 之外还会删除alg并默认以ext: true导入。单一命中与多命中错误处理解析函数在候选筛选后执行精确的命中数判断见 src/jwks/local.ts0 个命中抛出JWKSNoMatchingKeyERR_JWKS_NO_MATCHING_KEY恰好 1 个命中导入并返回该公钥多个命中抛出JWKSMultipleMatchingKeysERR_JWKS_MULTIPLE_MATCHING_KEYS且该错误对象实现了[Symbol.asyncIterator]可以被for await迭代依次产出每个候选公钥。这些错误均定义于 src/util/errors.ts并继承自统一的JOSEError基类每个错误子类带有稳定的code字符串便于以判别联合方式处理见AnyJOSEError类型src/util/errors.ts。多命中时的迭代式验证官方示例当 JWKS 中出现多个符合条件的公钥例如轮换期间新旧公钥并存时可以接力尝试验证逐个用候选公钥调用jwtVerify签名失败则继续下一个。官方文档给出了完整模式const options { issuer: urn:example:issuer, audience: urn:example:audience, } const { payload, protectedHeader } await jose .jwtVerify(jwt, JWKS, options) .catch(async (error) { if (error instanceof jose.errors.JWKSMultipleMatchingKeys) { for await (const publicKey of error) { try { return await jose.jwtVerify(jwt, publicKey, options) } catch (innerError) { if (innerError instanceof jose.errors.JWSSignatureVerificationFailed) { continue } throw innerError } } throw new jose.errors.JWSSignatureVerificationFailed() } throw error }) console.log(protectedHeader) console.log(payload)这段代码的关键点只有当错误是JWKSMultipleMatchingKeys时才进入迭代其余错误原样抛出迭代中仅当JWSSignatureVerificationFailedERR_JWS_SIGNATURE_VERIFICATION_FAILED时才继续下一个公钥其他错误立即抛出避免掩盖真正的问题全部候选都失败后显式抛出JWSSignatureVerificationFailed语义清晰。注意错误对象可迭代是实例化自本模块时才会真正产出公钥errors.ts中JWKSMultipleMatchingKeys类默认的[Symbol.asyncIterator]是个空生成器见 src/util/errors.ts手工new出来的实例不会迭代出任何东西。官方测试对行为的印证仓库中的 test/jwks/local.test.ts 直接印证了上述行为值得作为进一步阅读材料LocalJWKSet测试畸形输入同步抛ERR_JWKS_INVALIDjwks()返回深度相等但引用不同的克隆JWK use must be a stringuse: 0非字符串的 JWK 不会被选中抛出ERR_JWKS_NO_MATCHING_KEYJWK alg must be a stringalg: 0同理不匹配a non-string kid must not bypass key selection头部kid非字符串时不得绕过选择同样无匹配——这正是isUsableJWK中kid undefined || (typeof kid string kid jwkKid)的保护作用JWK key_ops must be an array of unique stringskey_ops为null、对象、字符串、数字、含重复元素或含非字符串元素的数组时均无法命中。这些测试共同说明了isUsableJWK对字段类型的严格校验任何类型不符的字段都会让该 JWK 落选而不是被宽容地忽略。实践建议与限制基于源码与文档总结几条使用createLocalJWKSet的实践要点构造时校验输入把 JWKS 的合法性校验提前到加载配置阶段尽早暴露配置错误保持 JWKS 中kid唯一避免在同一alg下多个公钥具有相同kid以免频繁触发多命中迭代路径轮换期善用多命中迭代新旧密钥并存时多命中迭代是处理不知道签名者用的是哪把钥的官方推荐模式注意适用边界本函数只解析验证签名的公钥加密JWE场景不适用对称算法HS*也不被接受缓存自动生效同一 JWK 在同一算法下的导入结果被缓存复用无需手动管理。如果需要进一步探索建议对照阅读本地实现源码、JWS 算法表、错误定义、本地 JWKS 测试以及与之互补的远程 JWKS 模块 docs/jwks/remote/README.md。赞分享网络安全认证鉴权后端【免费下载链接】joseJWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes项目地址https://gitcode.com/gh_mirrors/jo/jose点击查看免费下载相关推荐jose 本地 JWKS 公钥解析createLocalJWKSet 完全指南jose 本地 JWKS 公钥解析createLocalJWKSet 完全指南 本篇技术指南围绕 jose 库的 createLocalJWKSet 展开讲网络安全认证鉴权后端jose 远程 JWKS 密钥解析RemoteJWKSet 接口全解析jose 远程 JWKS 密钥解析RemoteJWKSet 接口全解析 本文围绕 jose 库中 createRemoteJWKSet 返回的密钥解析函数 R网络安全认证鉴权后端抖音自动上传工具一键批量发布视频的终极指南抖音自动上传工具一键批量发布视频的终极指南 抖音自动上传工具是一款专为内容创作者打造的自动化视频发布神器能够帮你实现从视频采集到发布的完整自动化流程。这款开工作流自动化网页爬虫视频处理上一篇10分钟掌握aops-diana模型配置MySQL/LVS/TPCC场景最佳实践 下一篇openeuler/yocto-meta-renesas常见问题解答新手必看的10个解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考