2. OAuth2.0 核心概念:资源所有者、客户端、授权服务器、资源服务器、访问令牌、刷新令牌

在支付订单系统中,OAuth2.0 并非一个简单的“黑盒”协议,而是一套由六个核心角色与令牌机制构成的授权框架。理解这些概念之间的边界与交互关系,是设计安全中间件的基础。本节将逐一拆解每个角色的职责,并通过结构图与对比表格建立全局认知。

2.1 六大核心角色与令牌定义

OAuth2.0 定义了四个基本角色和两种关键令牌,它们在支付场景中分别映射为具体的系统组件或用户实体:

角色/令牌 英文名称 支付订单系统映射 核心职责
资源所有者 Resource Owner 支付用户 / 商户 拥有订单数据、支付账户,授权第三方应用访问其资源
客户端 Client 商户后台 / 第三方支付应用 代表资源所有者请求授权,获取令牌并调用资源
授权服务器 Authorization Server 支付平台认证中心 验证资源所有者身份,颁发访问令牌与刷新令牌
资源服务器 Resource Server 订单API / 支付API 验证访问令牌,提供受保护的订单、支付数据
访问令牌 Access Token 短期凭证(如 JWT) 携带授权信息,用于调用资源服务器API
刷新令牌 Refresh Token 长期凭证(可选) 在访问令牌过期后,无感获取新的访问令牌
设计要点: 在支付订单系统中,资源所有者通常不是直接操作API的终端用户,而是拥有订单数据的商户或用户账户。客户端必须明确区分“代表谁”发起请求,这是授权范围(Scope)设计的起点。

2.2 角色交互流程与授权边界

下图展示了 OAuth2.0 核心角色在支付订单系统中的典型交互流程。注意,资源所有者与客户端之间通过用户代理(浏览器或移动端)交互,而授权服务器与资源服务器在支付平台内部通常是两个独立的服务实例。

OAuth2.0 核心角色交互流程(支付订单场景) 资源所有者 (支付用户/商户) 客户端 (商户后台) 授权服务器 (认证中心) 资源服务器 (订单API) ① 授权请求 ② 携带授权码/凭证 ③ 颁发访问令牌 ④ 携带令牌调用API ⑤ 返回订单数据 ⚠ 关键隔离原则: 客户端 永远不直接接触 资源所有者的密码或支付凭证;授权服务器是唯一验证身份的节点。 资源服务器只信任访问令牌,不关心令牌是如何获得的。

2.3 访问令牌 vs 刷新令牌:生命周期与安全策略

在支付订单系统中,令牌的生命周期管理直接关系到资金安全与用户体验。访问令牌和刷新令牌在设计上有明确的职责分离:

对比维度 访问令牌 (Access Token) 刷新令牌 (Refresh Token)
有效期 短(通常 15 分钟 ~ 2 小时) 长(通常 7 天 ~ 30 天,甚至更长)
存储位置 客户端内存 / 短期缓存 客户端安全存储(如 HttpOnly Cookie、Keychain)
传输范围 每次API请求都携带(Authorization Header) 仅在令牌刷新时传输(/token 端点)
泄露影响 攻击者可短时间访问资源,但窗口有限 攻击者可长期获取新访问令牌,危害极大
支付场景策略 必须验证签名、过期时间、Scope 必须绑定客户端ID,支持轮换(Rotation)
安全红线: 在支付订单系统中,刷新令牌必须支持轮换机制(每次刷新后颁发新刷新令牌,旧令牌立即失效)。这是防止刷新令牌泄露后导致长期权限被盗用的关键手段。同时,刷新令牌不应具备直接调用订单API的能力,它只能用于换取访问令牌。

2.4 令牌格式与结构示例

现代支付系统普遍采用 JWT(JSON Web Token) 作为访问令牌的格式。JWT 自包含用户身份、授权范围和过期时间,资源服务器无需回查授权服务器即可完成验证。以下是一个典型的支付订单系统访问令牌结构:

// JWT 访问令牌示例(Header.Payload.Signature)
// Header
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "payment-key-2025-01"
}
// Payload
{
  "sub": "merchant_12345",           // 资源所有者标识(商户ID)
  "client_id": "app_order_web",      // 客户端标识
  "scope": "order:read order:write", // 授权范围
  "iat": 1700000000,                 // 签发时间
  "exp": 1700003600,                 // 过期时间(1小时后)
  "jti": "unique-token-id-abc123",   // 令牌唯一ID(用于幂等与吊销)
  "custom:merchant_level": "premium" // 自定义声明(支付平台扩展)
}
// Signature: 使用授权服务器的RSA私钥对Header+Payload签名
幂等设计关联: 注意 Payload 中的 jti(JWT ID)字段。在支付订单系统中,jti 可作为令牌级别的幂等键。资源服务器在处理请求时,可以缓存已使用的 jti,防止同一个令牌被重放攻击。这是 OAuth2.0 与幂等设计结合的第一个关键点。

2.5 角色边界在支付系统中的实际划分

在微服务架构的支付平台中,授权服务器与资源服务器通常是物理分离的。下图展示了这种部署边界:

支付系统 OAuth2.0 角色部署边界 外部不可信网络 客户端 商户后台 / 第三方应用 支付平台内部可信网络 授权服务器 认证中心(颁发令牌) 资源服务器 订单API / 支付API 令牌存储 Redis / 数据库 • 访问令牌黑名单 • 刷新令牌哈希 • 客户端密钥 HTTPS 查询/存储 验证黑名单 🔒 资源服务器不直接访问授权服务器的数据库;令牌验证通过 JWT 签名 + 本地黑名单缓存完成,避免单点故障。

2.6 核心概念在幂等设计中的前置知识

在进入具体的中间件集成之前,请先建立以下认知映射,这将直接影响后续章节的幂等键设计与令牌校验逻辑:

  • 资源所有者 = 幂等键的归属主体: 幂等键通常需要绑定到具体的资源所有者(如 merchant_id),防止跨商户的幂等冲突。
  • 客户端 = 幂等键的生成者: 客户端在发起支付请求时生成全局唯一幂等键(如 Idempotency-Key 头),授权服务器和资源服务器均需验证该键的唯一性。
  • 访问令牌 = 幂等键的载体: 令牌中的 jti 可作为请求级别的幂等标识,资源服务器在写入订单前检查 jti 是否已被处理。
  • 刷新令牌 = 会话级别的幂等保障: 刷新令牌的轮换机制本身是一种幂等操作——每次刷新请求必须携带当前有效的刷新令牌,且一次刷新后旧令牌立即失效,防止重复刷新导致状态不一致。