JWT 生成与验证:核心流程与签名算法

JWT(JSON Web Token)在压测场景中是最常见的认证载体。压测脚本需要模拟客户端生成合法 Token,服务端则需在每次请求中验证 Token 的有效性。理解 JWT 的签发流程、签名算法及验证过程,是构建高保真压测模型的基础。

2.1 JWT 签发流程

JWT 签发是服务端在用户认证成功后,将用户身份信息编码为 Token 并返回给客户端的过程。标准签发流程包含以下步骤:

  1. 用户认证:客户端提交用户名/密码或第三方凭证,服务端验证通过后进入签发阶段。
  2. 构建 Payload:服务端将用户 ID、角色、过期时间(exp)、签发时间(iat)等声明放入 JSON 对象。
  3. 选择签名算法:根据安全策略选择 HMAC(对称)或 RSA/ECDSA(非对称)算法。
  4. 生成 Header:包含算法类型(alg)和 Token 类型(typ),例如 {"alg":"HS256","typ":"JWT"}。
  5. 签名计算:对 Base64Url 编码的 Header 和 Payload 进行签名,生成 Signature。
  6. 拼接 Token:将三部分用点号(.)连接,形成最终 JWT 字符串。
压测要点: 压测脚本中若需动态生成 JWT,必须确保每次签发的 Token 携带不同的 jti(JWT ID)或 iat,避免服务端因重复 Token 触发重放攻击检测。
JWT 签发流程 用户认证 构建 Payload 选择签名算法 生成 Header 签名计算(HMAC/RSA/ECDSA) 拼接 Token(Header.Payload.Signature) 说明:压测中若使用预生成 Token 池,需确保 Token 未过期且包含正确的用户上下文。 动态签发时注意密钥管理和签名性能开销。

2.2 HMAC 签名算法

HMAC(Hash-based Message Authentication Code)是对称签名算法,使用同一个密钥进行签名和验证。JWT 标准中常用的 HMAC 变体包括 HS256(SHA-256)、HS384(SHA-384)和 HS512(SHA-512)。

算法 哈希函数 签名长度(位) 密钥最小长度 压测性能
HS256 SHA-256 256 256 位(32 字节) 高(约 50K TPS)
HS384 SHA-384 384 384 位(48 字节) 中(约 40K TPS)
HS512 SHA-512 512 512 位(64 字节) 中低(约 30K TPS)
压测建议: HMAC 算法计算速度快,适合高并发压测场景。但密钥必须严格保密,压测环境中建议使用独立的测试密钥,避免泄露生产密钥。

HMAC 签名计算过程如下:

// 伪代码:HMAC-SHA256 签名
String header = base64UrlEncode(JSON.stringify({"alg":"HS256","typ":"JWT"}));
String payload = base64UrlEncode(JSON.stringify({"sub":"1234567890","name":"John Doe","iat":1516239022}));
String signature = HMACSHA256(header + "." + payload, secretKey);
String jwt = header + "." + payload + "." + signature;

2.3 RSA/ECDSA 非对称签名

非对称签名使用私钥签发、公钥验证,解决了对称算法中密钥分发和管理的安全问题。JWT 支持 RSA 系列(RS256、RS384、RS512)和 ECDSA 系列(ES256、ES384、ES512)。

算法族 算法 密钥对类型 签名长度 计算开销 适用场景
RSA RS256 / RS384 / RS512 RSA 公钥 + 私钥 256~512 位 高(签名慢,验证快) 服务端签发,多方验证
ECDSA ES256 / ES384 / ES512 椭圆曲线密钥对 64~132 字节 中(签名快,验证快) 移动端、IoT、高并发
压测风险提示: RSA 签名操作在 CPU 密集型场景下可能成为瓶颈。ECDSA 在同等安全强度下性能更优,但部分老旧库支持不完善。压测前需确认服务端签名/验证的 TPS 上限。

非对称签名的典型流程:

// 伪代码:RS256 签名与验证
// 签发端(使用私钥)
String signature = RSA_SHA256(header + "." + payload, privateKey);

// 验证端(使用公钥)
boolean isValid = RSA_VERIFY_SHA256(header + "." + payload, signature, publicKey);

2.4 JWT 验证过程

服务端收到 JWT 后,需按以下步骤验证其合法性:

  1. 解析 Token:按点号(.)分割,提取 Header、Payload、Signature 三部分。
  2. Base64Url 解码 Header:读取算法类型(alg),确认是否在服务端允许列表中。
  3. 算法验证:根据 Header 中的 alg 字段选择对应的验证算法。禁止使用 none 算法。
  4. 签名验证:使用密钥(对称)或公钥(非对称)重新计算签名,与 Token 中的 Signature 比对。
  5. Payload 校验:检查 exp(过期时间)、nbf(不早于)、iss(签发者)、aud(受众)等声明。
  6. 业务校验:验证用户 ID、角色等自定义声明是否有效。
JWT 验证流程 解析 Token(分割) Base64Url 解码 Header 算法验证(防 none 攻击) 签名验证(HMAC/RSA/ECDSA) Payload 校验(exp/nbf/iss/aud) 业务校验(用户 ID/角色) 验证通过 ✓ 验证失败时返回 401 并记录失败原因

2.5 压测场景中的 JWT 验证要点

  • Token 过期处理:压测脚本需监控 Token 过期时间,在过期前重新签发或使用刷新 Token。
  • 签名性能基线:记录服务端 JWT 验证的 P99 延迟,若超过 10ms 需考虑优化或升级算法。
  • 密钥轮转测试:模拟密钥轮转场景,验证服务端能否正确处理新旧密钥的过渡期。
  • 无效 Token 压测:构造签名错误、过期、算法篡改等无效 Token,验证服务端拒绝速度和错误处理能力。
压测诊断指标: JWT 验证成功率、验证平均延迟、验证 P99 延迟、无效 Token 拒绝率、密钥加载时间。