DevToolBox免费
博客

JWT 工作原理:JSON Web Token 完全指南

12 分钟阅读作者 DevToolBox

JSON Web Token (JWT) 是现代 Web 应用中最广泛使用的无状态认证标准。本指南详细解释 JWT 的工作原理、结构、安全最佳实践和常见陷阱。

什么是 JWT?

JWT 是一种紧凑的、URL 安全的令牌,用于在两方之间传递声明(数据)。它由三部分组成,用点分隔:Header.Payload.Signature。令牌经过 Base64URL 编码,适用于 HTTP 头、Cookie 和 URL。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

   Header          Payload              Signature
(algorithm)    (user claims)       (verification hash)

JWT 结构解析

Header(头部)

头部标识用于签名令牌的算法:

{
  "alg": "HS256",    // Algorithm: HMAC-SHA256
  "typ": "JWT"       // Token type
}

Payload(负载/声明)

负载包含声明 — 关于用户和元数据的信息:

{
  "sub": "1234567890",      // Subject (user ID)
  "name": "John Doe",       // Custom claim
  "email": "john@example.com",
  "role": "admin",           // Custom claim
  "iss": "https://api.example.com",  // Issuer
  "aud": "https://app.example.com",  // Audience
  "iat": 1516239022,        // Issued at (Unix timestamp)
  "exp": 1516242622         // Expiration (1 hour later)
}

Signature(签名)

签名确保令牌未被篡改:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret_key
)

JWT 认证流程

1. 用户向登录端点发送凭证(邮箱/密码)
2. 服务器验证凭证
3. 服务器用用户数据创建 JWT 并用密钥签名
4. 服务器将 JWT 返回给客户端
5. 客户端存储 JWT(httpOnly cookie 或内存)
6. 客户端在每次请求中通过 Authorization 头发送 JWT
7. 服务器验证签名并从负载中提取用户数据

JWT vs 基于 Session 的认证

FeatureJWT (Token-based)Session (Server-side)
StorageClient-side (cookie/memory)Server-side (database/Redis)
ScalabilityStateless — scales easilyRequires shared session store
Server loadNo DB lookup per requestDB/Redis lookup each request
RevocationHard (need blacklist)Easy (delete session)
SizeLarger (contains claims)Small session ID
Mobile-friendlyYes (no cookies needed)Harder without cookies
SecurityVulnerable if secret leakedVulnerable to session fixation

常见 JWT 声明

ClaimNameDescription
issIssuerWho created the token (e.g., your auth server URL)
subSubjectThe user or entity the token represents (usually user ID)
audAudienceIntended recipient (e.g., your API URL)
expExpirationUnix timestamp after which the token is invalid
iatIssued AtUnix timestamp when the token was created
nbfNot BeforeToken is not valid before this timestamp
jtiJWT IDUnique identifier to prevent token replay

安全最佳实践

  • 始终验证签名 — 不要信任未验证的 JWT。使用经过充分测试的库。
  • 使用短过期时间 — 将 exp 设置为 15-60 分钟。使用刷新令牌处理更长的会话。
  • 存储在 httpOnly cookie 中 — 防止 XSS 攻击读取令牌。添加 Secure 和 SameSite 标志。
  • 不要在负载中存储敏感数据 — JWT 负载是 Base64 编码的,不是加密的。任何人都可以解码。
  • 使用强密钥 — HMAC 至少使用 256 位随机性。RSA/EC 使用适当的密钥长度。
  • 实现令牌撤销 — 使用黑名单或短期令牌配合刷新令牌。

常见 JWT 漏洞

alg: "none" 攻击

攻击者修改头部以不使用算法。修复:始终在服务端验证算法,不接受 "none"。

密钥暴力破解

弱 HMAC 密钥可被暴力破解。修复:至少使用 256 位随机密钥。

令牌重放

被盗的令牌可在过期前被重用。修复:使用短过期时间,绑定 IP/设备,实现刷新令牌轮换。

实现示例

// Node.js with jsonwebtoken library
const jwt = require('jsonwebtoken');

// Sign (create token)
const token = jwt.sign(
  { sub: user.id, name: user.name, role: user.role },
  process.env.JWT_SECRET,
  { expiresIn: '1h', issuer: 'https://api.example.com' }
);

// Verify (validate token)
try {
  const decoded = jwt.verify(token, process.env.JWT_SECRET, {
    issuer: 'https://api.example.com',
    algorithms: ['HS256'],  // Prevent alg switching!
  });
  console.log(decoded.sub); // User ID
} catch (err) {
  // Token is invalid or expired
  console.error('JWT verification failed:', err.message);
}

// Express middleware
function authMiddleware(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'No token provided' });
  }
  const token = authHeader.split(' ')[1];
  try {
    req.user = jwt.verify(token, process.env.JWT_SECRET);
    next();
  } catch {
    return res.status(401).json({ error: 'Invalid token' });
  }
}

即时解码和检查任何 JWT

FAQ

JWT 是加密的吗?

不是。标准 JWT (JWS) 只是签名,未加密。负载是 Base64URL 编码的,任何人都可以解码。如需隐藏负载内容,使用 JWE。

应该将 JWT 存储在 localStorage 还是 cookie 中?

httpOnly cookie 更安全,因为 JavaScript 无法访问,防止 XSS 窃取令牌。localStorage 容易受 XSS 攻击但更容易实现。

如何处理 JWT 过期?

使用短期访问令牌(15-60分钟)配合长期刷新令牌。访问令牌过期时,用刷新令牌获取新的。

HS256 和 RS256 有什么区别?

HS256 使用共享密钥签名和验证。RS256 使用私钥签名、公钥验证 — 适合分布式系统。

可以撤销 JWT 吗?

JWT 是无状态的,不能直接撤销。常见方法:维护令牌黑名单、使用极短过期时间、或在数据库中实现令牌版本系统。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

JWTJWT DecoderB64Base64 Encoder/DecoderJPJWT ParserJVJWT Validator

相关文章

JSON vs YAML vs TOML:你应该用哪种配置格式?

比较 JSON、YAML 和 TOML 配置格式,了解语法、特性和优缺点,选择适合你项目的格式。

API 认证:OAuth 2.0 vs JWT vs API Key

比较 API 认证方式:OAuth 2.0、JWT Bearer Token 和 API Key。了解每种方式的适用场景、安全权衡和实现模式。