服务端与数据 / 进阶
JWT 登录设计:短访问令牌与可撤销刷新令牌
使用短期 Access Token 处理 API 授权,使用服务端可追踪的 Refresh Token 延长会话,并通过轮换检测令牌重放。
两个令牌解决不同问题
Access Token:有效期 5 到 15 分钟,包含最少授权声明,API 本地验签;Refresh Token:有效期更长,只发送给刷新端点,服务端保存哈希和会话状态。
短访问令牌缩小泄露窗口,可撤销刷新令牌则提供退出登录、封禁设备和会话管理能力。不要在 JWT 中放密码、身份证号或频繁变化的权限明细。
验签之后还要验证声明
不要根据令牌头部任意接受算法。服务端应明确 issuer、audience、algorithms 和 token type。
EXAMPLE / 02JWT
import { jwtVerify } from 'jose';
const { payload } = await jwtVerify(token, publicKey, {
issuer: 'https://auth.example.com',
audience: 'orders-api',
algorithms: ['RS256'],
clockTolerance: 5
});
if (!payload.sub || payload.type !== 'access') {
throw new Error('invalid token claims');
}刷新时轮换并检测重放
每次刷新都作废旧 Refresh Token 并签发新令牌。如果已作废的令牌再次出现,说明令牌可能被复制,应撤销这一 token family 的全部会话。浏览器场景通常把 Refresh Token 放在 HttpOnly、Secure、SameSite 合适的 Cookie 中,并为刷新端点补充 CSRF 防护。
数据库只保存刷新令牌哈希,不保存明文;退出登录撤销当前会话,而不是等待过期;密钥轮换时用 kid 标记签名密钥,并保留过渡期公钥。