JWT 生成与验证:核心流程与签名算法
JWT(JSON Web Token)在压测场景中是最常见的认证载体。压测脚本需要模拟客户端生成合法 Token,服务端则需在每次请求中验证 Token 的有效性。理解 JWT 的签发流程、签名算法及验证过程,是构建高保真压测模型的基础。
2.1 JWT 签发流程
JWT 签发是服务端在用户认证成功后,将用户身份信息编码为 Token 并返回给客户端的过程。标准签发流程包含以下步骤:
- 用户认证:客户端提交用户名/密码或第三方凭证,服务端验证通过后进入签发阶段。
- 构建 Payload:服务端将用户 ID、角色、过期时间(exp)、签发时间(iat)等声明放入 JSON 对象。
- 选择签名算法:根据安全策略选择 HMAC(对称)或 RSA/ECDSA(非对称)算法。
- 生成 Header:包含算法类型(alg)和 Token 类型(typ),例如
{"alg":"HS256","typ":"JWT"}。 - 签名计算:对 Base64Url 编码的 Header 和 Payload 进行签名,生成 Signature。
- 拼接 Token:将三部分用点号(.)连接,形成最终 JWT 字符串。
压测要点: 压测脚本中若需动态生成 JWT,必须确保每次签发的 Token 携带不同的 jti(JWT ID)或 iat,避免服务端因重复 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 后,需按以下步骤验证其合法性:
- 解析 Token:按点号(.)分割,提取 Header、Payload、Signature 三部分。
- Base64Url 解码 Header:读取算法类型(alg),确认是否在服务端允许列表中。
- 算法验证:根据 Header 中的 alg 字段选择对应的验证算法。禁止使用
none算法。 - 签名验证:使用密钥(对称)或公钥(非对称)重新计算签名,与 Token 中的 Signature 比对。
- Payload 校验:检查 exp(过期时间)、nbf(不早于)、iss(签发者)、aud(受众)等声明。
- 业务校验:验证用户 ID、角色等自定义声明是否有效。
2.5 压测场景中的 JWT 验证要点
- Token 过期处理:压测脚本需监控 Token 过期时间,在过期前重新签发或使用刷新 Token。
- 签名性能基线:记录服务端 JWT 验证的 P99 延迟,若超过 10ms 需考虑优化或升级算法。
- 密钥轮转测试:模拟密钥轮转场景,验证服务端能否正确处理新旧密钥的过渡期。
- 无效 Token 压测:构造签名错误、过期、算法篡改等无效 Token,验证服务端拒绝速度和错误处理能力。
压测诊断指标: JWT 验证成功率、验证平均延迟、验证 P99 延迟、无效 Token 拒绝率、密钥加载时间。