4. JWT 生成与签发:服务端核心流程与标准声明

JWT 的生成与签发是分布式鉴权的第一道防线。服务端在用户认证通过后,按照 RFC 7519 规范构造 JWT 载荷,并使用签名算法对令牌进行加密保护。本章聚焦服务端生成 JWT 的完整流程,以及四个关键注册声明(Registered Claims):exp、iss、sub、aud 的设置规范与最佳实践。

4.1 服务端生成 JWT 的标准流程

JWT 的生成过程分为三个核心阶段:载荷组装 → 签名计算 → 令牌序列化。以下流程图展示了服务端签发 JWT 的完整链路:

JWT 服务端签发流程 JWT 服务端签发流程 用户认证通过 组装 JWT 载荷(Payload) 选择签名算法(HS256/RS256) 计算签名(Signature) 输出 JWT 令牌(Token)
关键要点: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 的组合可以有效防止令牌在服务间被重放攻击。