jose、jsonwebtoken、jwa、jws 和 node-jose 都是用于处理 JSON Web Token (JWT) 及相关加密标准的库,但它们的定位和适用场景各不相同。jsonwebtoken 是 Node.js 生态中最经典的选择,而 jose 则是现代化的跨平台替代方案。jws 和 jwa 提供了更底层的签名和算法支持,通常用于构建自定义协议。node-jose 是较早期的实现,目前建议优先评估 jose。
在 JavaScript 生态中处理身份验证和数据交换时,JSON Web Token (JWT) 是核心标准。然而,围绕 JWT 的库众多,从高层封装到底层原语各不相同。jose、jsonwebtoken、node-jose 提供了不同层次的抽象,而 jws 和 jwa 则关注更底层的签名和算法。本文将深入对比这些库的技术细节,帮助你在架构决策中做出正确选择。
jose 提供了现代化的 Promise 基于 API,支持 ESM 和 CJS。
SignJWT 类进行链式调用。jwtVerify 函数。// jose: 签名
import { SignJWT } from 'jose';
const jwt = await new SignJWT({ 'urn:example:claim': true })
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.sign(secret);
// jose: 验证
import { jwtVerify } from 'jose';
const { payload } = await jwtVerify(jwt, secret);
jsonwebtoken 是经典的回调风格 API,也支持 Promise。
// jsonwebtoken: 签名
const jwt = require('jsonwebtoken');
const token = jwt.sign({ foo: 'bar' }, secret, { algorithm: 'HS256' });
// jsonwebtoken: 验证
const decoded = jwt.verify(token, secret, { algorithms: ['HS256'] });
node-jose 提供了基于 Promise 的 API,但风格较旧。
jose 简洁。// node-jose: 签名
const jose = require('node-jose');
const signature = await jose.JWS.createSign({ format: 'compact' }, key)
.update(JSON.stringify(payload))
.final();
// node-jose: 验证
const verified = await jose.JWS.createVerify(key)
.verify(signature);
jws 专注于 JSON Web Signature 底层实现。
// jws: 签名
const jws = require('jws');
const token = jws.sign({
header: { alg: 'HS256' },
payload: { foo: 'bar' },
secret: 'shhhhh'
});
jwa 处理底层算法逻辑。
// jwa: 算法实例
const jwa = require('jwa');
const hmac = jwa('HS256');
const sig = hmac.sign('data', 'secret');
jose 是为同构环境设计的。
// jose: 浏览器环境同样适用
// 无需更改代码,自动检测环境
import { generateKeyPair } from 'jose';
const { publicKey, privateKey } = await generateKeyPair('RS256');
jsonwebtoken 主要针对 Node.js 服务器。
crypto 模块。// jsonwebtoken: 仅限 Node.js
// 在浏览器中运行会报错,因为依赖 process.env 和 node crypto
const jwt = require('jsonwebtoken');
node-jose 支持 Node.js 和部分浏览器环境。
jose 轻量。// node-jose: 浏览器需要额外配置
// 通常不建议在现代前端架构中使用
jws 和 jwa 是 Node.js 优先的底层库。
// jws/jwa: 主要在 Node.js 环境使用
// 浏览器端使用需谨慎
jose 默认禁止不安全算法。
none 算法,防止签名绕过。// jose: 强制指定算法
// 如果不指定,默认安全配置生效
await jwtVerify(jwt, key, { algorithms: ['RS256'] });
jsonwebtoken 历史上存在算法混淆风险。
none。algorithms 选项以确保安全。// jsonwebtoken: 必须显式指定算法
jwt.verify(token, key, { algorithms: ['RS256'] });
node-jose 支持广泛的 JWS/JWE 算法。
// node-jose: 支持 JWE
const encrypted = await jose.JWE.createEncrypt({ format: 'compact' }, key)
.update(JSON.stringify(payload))
.final();
jws 和 jwa 提供原始能力。
// jws: 不验证算法安全性
// 开发者需确保 header 中的 alg 是可信的
| 特性 | jose | jsonwebtoken | node-jose | jws / jwa |
|---|---|---|---|---|
| 定位 | 现代化全平台库 | 经典 Node.js 库 | 旧版全平台库 | 底层原语 |
| 环境 | Node + 浏览器 | 仅 Node.js | Node + 浏览器 | 主要 Node.js |
| API 风格 | Promise / Class | Callback / Promise | Promise | Sync / Callback |
| 安全性 | 默认安全配置 | 需手动配置 | 需手动配置 | 无默认保护 |
| 维护状态 | 活跃 | 稳定 | 缓慢 | 稳定 |
| 推荐场景 | 新项目 / 同构 | legacy 后端 | 遗留系统兼容 | 自定义协议 |
jose 是目前最稳健的选择 🛡️。它解决了 jsonwebtoken 在浏览器端不可用的问题,同时提供了更安全的默认配置。如果你的项目需要前端验证令牌,或者你希望采用现代 ESM 模块标准,jose 是唯一推荐。
jsonwebtoken 依然有价值 📦。对于仅运行在 Node.js 上的传统后端服务,它的 API 简单且社区资源丰富。如果迁移成本过高,继续使用它是可以的,但务必注意配置安全选项。
node-jose 建议逐步淘汰 🕰️。除非你有明确的兼容性需求,否则应迁移至 jose。jose 由同一作者维护,代表了最新的技术方向。
jws 和 jwa 是构建块 🧱。不要直接用它们来处理用户身份验证。仅在你需要实现非标准的 JWT 扩展或底层加密工具时使用。
核心原则:安全优于便利。选择默认禁止不安全算法的库,并始终在验证时显式指定允许的算法列表。
选择 jose 如果你需要同时支持 Node.js 和浏览器环境,或者希望使用基于 Web Crypto API 的现代实现。它是目前最推荐的新项目首选,安全性更高且维护活跃。
选择 jws 仅当你需要手动控制 JWS 签名结构的底层细节,而不是使用封装好的 JWT 逻辑。通常不建议直接用于常规身份验证。
选择 jwa 仅当你需要单独处理 JSON Web Algorithms 算法逻辑,例如自定义加密流程。它是底层构建块,不适合直接处理令牌。
选择 jsonwebtoken 如果你维护的是传统的 Node.js 后端项目,且依赖其简单的 API 和庞大的社区示例。适合不需要浏览器支持的后端服务。
选择 node-jose 仅当你需要兼容旧的 enterprise 系统或特定遗留代码库。新项目应优先使用 jose 以获得更好的性能和长期支持。
jose is a JavaScript module for JSON Object Signing and Encryption, providing support for JSON Web Tokens (JWT), JSON Web Signature (JWS), JSON Web Encryption (JWE), JSON Web Key (JWK), JSON Web Key Set (JWKS), and more. The module is designed to work across various Web-interoperable runtimes including Node.js, browsers, Cloudflare Workers, Deno, Bun, and others.
If you want to quickly add JWT authentication to JavaScript apps, feel free to check out Auth0's JavaScript SDK and free plan. Create an Auth0 account; it's free!
Support from the community to continue maintaining and improving this module is welcome. If you find the module useful, please consider supporting the project by becoming a sponsor.
jose has no dependencies and it exports tree-shakeable ESM1.
jose is distributed via npmjs.com, jsr.io, jsdelivr.com, and github.com.
example ESM import1
import * as jose from 'jose'
The jose module supports JSON Web Tokens (JWT) and provides functionality for signing and verifying tokens, as well as their JWT Claims Set validation.
jwtVerify function
SignJWT classThe jose module supports encrypted JSON Web Tokens and provides functionality for encrypting and decrypting tokens, as well as their JWT Claims Set validation.
jwtDecrypt functionEncryptJWT classThe jose module supports importing, exporting, and generating keys and secrets in various formats, including PEM formats like SPKI, X.509 certificate, and PKCS #8, as well as JSON Web Key (JWK).
The jose module supports signing and verification of JWS messages with arbitrary payloads in Compact, Flattened JSON, and General JSON serialization syntaxes.
The jose module supports encryption and decryption of JWE messages with arbitrary plaintext in Compact, Flattened JSON, and General JSON serialization syntaxes.
The following are additional features and utilities provided by the jose module:
The jose module is compatible with JavaScript runtimes that support the utilized Web API globals and standard built-in objects or are Node.js.
The following runtimes are supported (this is not an exhaustive list):
Please note that certain algorithms may not be available depending on the runtime used. You can find a list of available algorithms for each runtime in the specific issue links provided above.
| Version | Security Fixes 🔑 | Other Bug Fixes 🐞 | New Features ⭐ | Runtime and Module type |
|---|---|---|---|---|
| v6.x | Security Policy | ✅ | ✅ | Universal2 ESM1 |
The algorithm implementations in jose have been tested using test vectors from their respective specifications as well as RFC7520.