4. JWT 生成与签发:服务端核心流程与标准声明
JWT 的生成与签发是分布式鉴权的第一道防线。服务端在用户认证通过后,按照 RFC 7519 规范构造 JWT 载荷,并使用签名算法对令牌进行加密保护。本章聚焦服务端生成 JWT 的完整流程,以及四个关键注册声明(Registered Claims):exp、iss、sub、aud 的设置规范与最佳实践。
4.1 服务端生成 JWT 的标准流程
JWT 的生成过程分为三个核心阶段:载荷组装 → 签名计算 → 令牌序列化。以下流程图展示了服务端签发 JWT 的完整链路:
关键要点:JWT 的生成必须在服务端完成,私钥或密钥绝不能暴露给客户端。签名算法推荐使用 RS256(非对称)以支持分布式密钥分发。
4.2 设置过期时间(exp)
exp(Expiration Time)是 JWT 中最重要的安全声明,用于限制令牌的有效期。服务端在签发时必须设置合理的过期时间,防止令牌被长期滥用。
| 参数 | 说明 | 推荐值 |
|---|---|---|
| exp | 令牌过期时间戳(Unix 时间,秒级) | 15 分钟 ~ 2 小时 |
| iat | 令牌签发时间戳(Issued At) | 当前服务器时间 |
| nbf | 令牌生效时间(Not Before),可选 | 与 iat 相同或略晚 |
最佳实践:访问令牌(Access Token)的 exp 建议设置为 15-30 分钟;刷新令牌(Refresh Token)的 exp 可设置为 7-30 天。服务端应校验 exp 是否大于当前时间,过期令牌必须拒绝。
4.3 设置签发者(iss)
iss(Issuer)声明标识 JWT 的签发方。在分布式系统中,iss 用于区分不同服务或认证中心签发的令牌,是令牌来源验证的关键字段。
- 格式规范:通常使用 URI 或服务名称,如
"iss": "https://auth.example.com" - 唯一性:每个签发者应使用全局唯一的标识符,避免跨系统冲突
- 验证逻辑:接收方必须校验 iss 是否属于可信签发者列表
- 多签发者场景:微服务架构中,不同服务可拥有独立的 iss,便于审计和权限隔离
4.4 设置主题(sub)
sub(Subject)声明标识 JWT 的主体,通常是用户 ID、设备 ID 或服务账号。sub 是令牌的核心载荷,接收方通过 sub 识别当前请求的实体身份。
| 场景 | sub 取值示例 | 说明 |
|---|---|---|
| 用户认证 | "sub": "user_12345" |
用户唯一标识 |
| 服务间调用 | "sub": "service_payment" |
服务账号名称 |
| 设备认证 | "sub": "device_imei_xxxx" |
设备硬件标识 |
安全提醒:sub 字段不应包含敏感信息(如明文密码、身份证号)。sub 仅用于标识身份,权限控制应通过其他声明(如 roles、permissions)实现。
4.5 设置受众(aud)
aud(Audience)声明标识 JWT 的目标接收方。在分布式系统中,aud 用于限制令牌只能被特定的服务或资源使用,防止令牌被跨服务滥用。
- 单受众:字符串形式,如
"aud": "https://api.example.com/orders" - 多受众:数组形式,如
"aud": ["https://api.example.com/orders", "https://api.example.com/users"] - 验证要求:接收方必须校验 aud 是否包含自身标识,不匹配则拒绝令牌
- 典型应用:API 网关根据 aud 将令牌路由到对应微服务,实现细粒度令牌隔离
4.6 完整 JWT 载荷示例
以下是一个符合 RFC 7519 规范的 JWT 载荷示例,包含四个核心注册声明:
{
"iss": "https://auth.example.com", // 签发者
"sub": "user_12345", // 主题(用户ID)
"aud": "https://api.example.com/orders", // 受众(目标服务)
"exp": 1735689600, // 过期时间(Unix时间戳)
"iat": 1735686000, // 签发时间
"nbf": 1735686000, // 生效时间
"jti": "token_uuid_abc123", // 令牌唯一ID(防重放)
"roles": ["admin", "editor"] // 自定义声明
}
编码后 JWT 示例:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJzdWIiOiJ1c2VyXzEyMzQ1IiwiYXVkIjoiaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20vb3JkZXJzIiwiZXhwIjoxNzM1Njg5NjAwLCJpYXQiOjE3MzU2ODYwMDAsIm5iZiI6MTczNTY4NjAwMCwianRpIjoidG9rZW5fdXVpZF9hYmMxMjMiLCJyb2xlcyI6WyJhZG1pbiIsImVkaXRvciJdfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
4.7 声明设置对比与避坑指南
| 声明 | 必须设置 | 常见错误 | 正确做法 |
|---|---|---|---|
| exp | 是 | 不设置或设置过长(如1年) | 15分钟~2小时,配合刷新令牌 |
| iss | 推荐 | 使用不明确的字符串 | 使用完整的 URI 或服务域名 |
| sub | 是 | 使用自增数字 ID | 使用 UUID 或业务唯一标识 |
| aud | 推荐 | 不设置或设置为通配符 | 明确指定目标服务 URL 或名称 |
分布式系统建议:在微服务架构中,建议统一使用 RS256 签名算法,由认证中心持有私钥签发 JWT,各微服务通过公钥验证令牌。iss 和 aud 的组合可以有效防止令牌在服务间被重放攻击。