jose vs jws vs jwa vs jsonwebtoken vs node-jose
JavaScript 生态中的 JWT 处理方案选型
josejwsjwajsonwebtokennode-jose类似的npm包:

JavaScript 生态中的 JWT 处理方案选型

jose、jsonwebtoken、jwa、jws 和 node-jose 都是用于处理 JSON Web Token (JWT) 及相关加密标准的库,但它们的定位和适用场景各不相同。jsonwebtoken 是 Node.js 生态中最经典的选择,而 jose 则是现代化的跨平台替代方案。jws 和 jwa 提供了更底层的签名和算法支持,通常用于构建自定义协议。node-jose 是较早期的实现,目前建议优先评估 jose。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
jose100,670,8227,759248 kB06 天前MIT
jws68,851,76372118.8 kB339 个月前MIT
jwa68,432,37210314.1 kB181 年前MIT
jsonwebtoken018,19043.4 kB2089 个月前MIT
node-jose0721353 kB734 年前Apache-2.0

JavaScript JWT 库深度对比:jose vs jsonwebtoken vs node-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。

  • API 简单直观,适合快速开发。
  • 在 Node.js 后端非常普及。
  • 需要注意配置选项以防止安全漏洞。
// 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,但风格较旧。

  • 支持 JWS 和 JWE 标准。
  • 代码结构相对繁琐,不如 jose 简洁。
  • 适用于需要特定 JWS 格式兼容的场景。
// 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 底层实现。

  • 不处理 JWT claims(如 exp, iat),只处理签名本身。
  • 适合需要自定义负载结构的场景。
// jws: 签名
const jws = require('jws');
const token = jws.sign({
  header: { alg: 'HS256' },
  payload: { foo: 'bar' },
  secret: 'shhhhh'
});

jwa 处理底层算法逻辑。

  • 用于创建签名实例或验证算法支持。
  • 通常不直接用于生成 JWT,而是作为构建块。
// jwa: 算法实例
const jwa = require('jwa');
const hmac = jwa('HS256');
const sig = hmac.sign('data', 'secret');

🌍 运行环境:Node.js 与浏览器

jose 是为同构环境设计的。

  • 在 Node.js 中使用 Crypto 模块。
  • 在浏览器中使用 Web Crypto API。
  • 无需配置打包工具即可在两端运行。
// jose: 浏览器环境同样适用
// 无需更改代码,自动检测环境
import { generateKeyPair } from 'jose';
const { publicKey, privateKey } = await generateKeyPair('RS256');

jsonwebtoken 主要针对 Node.js 服务器。

  • 依赖 Node.js 的 crypto 模块。
  • 在浏览器中无法直接使用,需要 polyfill 或替代方案。
  • 适合纯后端服务。
// jsonwebtoken: 仅限 Node.js
// 在浏览器中运行会报错,因为依赖 process.env 和 node crypto
const jwt = require('jsonwebtoken'); 

node-jose 支持 Node.js 和部分浏览器环境。

  • 通过 shim 支持浏览器,但配置较复杂。
  • 体积较大,不如 jose 轻量。
// node-jose: 浏览器需要额外配置
// 通常不建议在现代前端架构中使用

jws 和 jwa 是 Node.js 优先的底层库。

  • 主要设计用于服务器端签名逻辑。
  • 浏览器支持有限,需自行处理兼容性问题。
// jws/jwa: 主要在 Node.js 环境使用
// 浏览器端使用需谨慎

🔒 安全性与算法支持

jose 默认禁止不安全算法。

  • 不支持 none 算法,防止签名绕过。
  • 明确指定允许的算法列表,减少配置错误。
  • actively 维护,修复漏洞迅速。
// jose: 强制指定算法
// 如果不指定,默认安全配置生效
await jwtVerify(jwt, key, { algorithms: ['RS256'] });

jsonwebtoken 历史上存在算法混淆风险。

  • 早期版本允许攻击者更改算法为 none。
  • 现在需要显式指定 algorithms 选项以确保安全。
  • 社区庞大,安全审计较多。
// jsonwebtoken: 必须显式指定算法
jwt.verify(token, key, { algorithms: ['RS256'] }); 

node-jose 支持广泛的 JWS/JWE 算法。

  • 适合需要复杂加密场景(如 JWE 加密负载)。
  • 配置不当可能导致安全风险。
// node-jose: 支持 JWE
const encrypted = await jose.JWE.createEncrypt({ format: 'compact' }, key)
  .update(JSON.stringify(payload))
  .final();

jws 和 jwa 提供原始能力。

  • 不阻止不安全算法,开发者需自行负责。
  • 适合构建自定义安全协议,而非直接使用。
// jws: 不验证算法安全性
// 开发者需确保 header 中的 alg 是可信的

📊 总结对比表

特性josejsonwebtokennode-josejws / jwa
定位现代化全平台库经典 Node.js 库旧版全平台库底层原语
环境Node + 浏览器仅 Node.jsNode + 浏览器主要 Node.js
API 风格Promise / ClassCallback / PromisePromiseSync / Callback
安全性默认安全配置需手动配置需手动配置无默认保护
维护状态活跃稳定缓慢稳定
推荐场景新项目 / 同构legacy 后端遗留系统兼容自定义协议

💡 最终建议

jose 是目前最稳健的选择 🛡️。它解决了 jsonwebtoken 在浏览器端不可用的问题,同时提供了更安全的默认配置。如果你的项目需要前端验证令牌,或者你希望采用现代 ESM 模块标准,jose 是唯一推荐。

jsonwebtoken 依然有价值 📦。对于仅运行在 Node.js 上的传统后端服务,它的 API 简单且社区资源丰富。如果迁移成本过高,继续使用它是可以的,但务必注意配置安全选项。

node-jose 建议逐步淘汰 🕰️。除非你有明确的兼容性需求,否则应迁移至 jose。jose 由同一作者维护,代表了最新的技术方向。

jws 和 jwa 是构建块 🧱。不要直接用它们来处理用户身份验证。仅在你需要实现非标准的 JWT 扩展或底层加密工具时使用。

核心原则:安全优于便利。选择默认禁止不安全算法的库,并始终在验证时显式指定允许的算法列表。

如何选择: jose vs jws vs jwa vs jsonwebtoken vs node-jose

  • jose:

    选择 jose 如果你需要同时支持 Node.js 和浏览器环境,或者希望使用基于 Web Crypto API 的现代实现。它是目前最推荐的新项目首选,安全性更高且维护活跃。

  • jws:

    选择 jws 仅当你需要手动控制 JWS 签名结构的底层细节,而不是使用封装好的 JWT 逻辑。通常不建议直接用于常规身份验证。

  • jwa:

    选择 jwa 仅当你需要单独处理 JSON Web Algorithms 算法逻辑,例如自定义加密流程。它是底层构建块,不适合直接处理令牌。

  • jsonwebtoken:

    选择 jsonwebtoken 如果你维护的是传统的 Node.js 后端项目,且依赖其简单的 API 和庞大的社区示例。适合不需要浏览器支持的后端服务。

  • node-jose:

    选择 node-jose 仅当你需要兼容旧的 enterprise 系统或特定遗留代码库。新项目应优先使用 jose 以获得更好的性能和长期支持。

jose的README

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.

Sponsor

Auth0 by Okta

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!

💗 Help the project

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.

Dependencies: 0

jose has no dependencies and it exports tree-shakeable ESM1.

Documentation

jose is distributed via npmjs.com, jsr.io, jsdelivr.com, and github.com.

example ESM import1

import * as jose from 'jose'

JSON Web Tokens (JWT)

The jose module supports JSON Web Tokens (JWT) and provides functionality for signing and verifying tokens, as well as their JWT Claims Set validation.

Encrypted JSON Web Tokens

The jose module supports encrypted JSON Web Tokens and provides functionality for encrypting and decrypting tokens, as well as their JWT Claims Set validation.

Key Utilities

The 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).

JSON Web Signature (JWS)

The jose module supports signing and verification of JWS messages with arbitrary payloads in Compact, Flattened JSON, and General JSON serialization syntaxes.

JSON Web Encryption (JWE)

The jose module supports encryption and decryption of JWE messages with arbitrary plaintext in Compact, Flattened JSON, and General JSON serialization syntaxes.

Other

The following are additional features and utilities provided by the jose module:

Supported Runtimes

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.

Supported Versions

VersionSecurity Fixes 🔑Other Bug Fixes 🐞New Features ⭐Runtime and Module type
v6.xSecurity Policy✅✅Universal2 ESM1

Specifications

Details
  • JSON Web Signature (JWS) - RFC7515
  • JSON Web Encryption (JWE) - RFC7516
  • JSON Web Key (JWK) - RFC7517
  • JSON Web Algorithms (JWA) - RFC7518
  • JSON Web Token (JWT) - RFC7519
  • JSON Web Key Thumbprint - RFC7638
  • JSON Web Key Thumbprint URI - RFC9278
  • JWS Unencoded Payload Option - RFC7797
  • CFRG Elliptic Curve ECDH and Signatures - RFC8037
  • Fully-Specified Algorithms for JOSE - RFC9864
  • ML-DSA for JOSE - RFC9964

The algorithm implementations in jose have been tested using test vectors from their respective specifications as well as RFC7520.

Footnotes

  1. CJS style let jose = require('jose') is possible in Node.js versions where the require(esm) feature is enabled by default (^20.19.0 || ^22.12.0 || >= 23.0.0). ↩ ↩2 ↩3

  2. Assumes runtime support of WebCryptoAPI and Fetch API ↩