跳到主要内容
版本:3.1

Rpc鉴权授权策略

一、说明

鉴权授权策略,用于控制RPC请求的访问权限。是现代api-server的系统最重要的功能之一。

一般的鉴权授权策略可以分为2个大类:

  1. 基于会话
  2. 基于Token

而基于Token的鉴权授权策略又分为2大类:

  1. 基于随机字符串的Token
  2. 基于结构化的Token(例如:JWT)

二、基于会话的鉴权授权策略

基于会话的鉴权授权策略,一般是只应用于面向连接的通信。一般的这种通信具有持久化的特性,并且是有状态的。

三、基于Token的鉴权授权策略

基于Token的鉴权授权策略,一般用于面向消息的通信。

3.1 基于随机字符串的Token

3.2 基于结构化的Token(例如:JWT)

四、鉴权授权策略的比较

好的,我们来详细比较一下随机字符串(通常指无结构会话令牌)和 JWT(JSON Web Token)的优缺点以及适用场景。

核心区别:

  • 随机字符串 (无结构令牌): 本质上就是一个不可预测的长字符串(如 f8a3d7c0b1e9)。它本身不包含任何有意义的信息,只是一个指向服务器端存储(通常是数据库或缓存)中会话数据的引用
  • JWT (结构化令牌): 是一个经过数字签名或加密的、自包含的结构化字符串。它由三部分组成(Header.Payload.Signature),其中 Payload 部分包含了声明(通常是关于用户身份和权限的 JSON 对象)。服务器可以验证其签名/加密,并直接从中提取信息,无需查询后端存储(至少在有效期内)。

4.1 随机字符串 (无结构会话令牌)

  • 优点:

    1. 简单轻量: 生成和验证极其简单快速(生成随机数 -> 存储;收到请求 -> 查存储)。
    2. 完全控制: 服务器拥有绝对控制权。可以即时撤销(删除存储条目)、修改关联数据(更新存储条目)或强制过期。
    3. 无信息泄露: 令牌本身不包含任何用户或会话信息,即使被截获,攻击者也无法从中直接获取有效内容(前提是字符串本身足够随机)。
    4. 存储开销可控: 服务器端存储的大小和内容完全由应用决定。
    5. 天然防篡改: 篡改令牌会导致在服务器端存储中查找失败,验证直接不通过。
  • 缺点:

    1. 状态性: 服务器必须维护一个存储(数据库、Redis 等)来关联令牌和实际的会话数据。这引入了状态。
    2. 数据库/缓存依赖: 每次验证令牌都需要查询后端存储。在高并发场景下,这可能成为性能瓶颈和单点故障。
    3. 扩展性挑战: 在分布式系统或微服务架构中,需要共享会话存储(例如集中式 Redis 集群)或实现粘性会话(Session Affinity),增加了复杂性和潜在瓶颈。
    4. 无内置信息: 令牌本身不携带任何信息,所有数据都需要从存储中获取。
  • 典型使用场景:

    1. 传统的 Web 应用会话管理: 这是最经典的场景。用户登录后,服务器创建会话数据存储在服务端(内存、数据库、Redis),生成一个随机的 Session ID(通常存储在 Cookie 中)返回给浏览器。后续请求携带此 ID,服务器查询存储获取会话状态。
    2. 一次性令牌: 如密码重置令牌、邮箱验证令牌。它们通常是随机字符串,存储在数据库并关联特定操作和过期时间,使用一次即失效。
    3. 简单的 API 认证(较少见): 如果 API 调用频率不高或架构简单,也可以使用类似机制(API Key + Secret,但 Secret 通常也需要存储和验证)。
    4. 需要即时撤销能力的场景: 如用户登出、管理员踢人下线等,需要立即使令牌失效的场景。

4.2 JWT (JSON Web Token)

  • 优点:

    1. 无状态: 这是 JWT 最大的优势。服务器不需要在本地或共享存储中保存会话状态。验证仅依赖于签名(和可选的加密)以及预定义的密钥/证书。极大简化了服务器架构,消除了数据库查询瓶颈。
    2. 自包含: Payload 中可以携带有用的声明(用户名、用户ID、角色、权限、过期时间等)。验证通过后,服务器可以直接使用这些信息,无需额外查询。
    3. 扩展性极佳: 完美适应分布式系统和微服务架构。任何服务实例只要拥有验证签名/解密的密钥,都可以独立验证令牌并提取所需信息。天然支持跨域/跨服务认证。
    4. 性能(特定场景): 避免了每次请求的存储查询开销(验证签名的计算开销通常远小于网络 I/O 和数据库查询)。在分布式系统中,优势尤其明显。
    5. 标准化: 是 IETF 标准 (RFC 7519),有成熟的库支持多种语言,互操作性好。
  • 缺点:

    1. 体积较大: 由于是 Base64 编码的 JSON,通常比随机字符串长很多。在带宽敏感或需频繁传输的场景(如放在 HTTP Header 中)可能成为负担。
    2. 难以主动撤销/失效: 一旦签发,在自然过期前,很难强制使其失效(因为服务端无状态)。实现主动撤销需要额外机制(如黑名单、短期有效期 + Refresh Token),增加了复杂性。
    3. 安全风险:
      • 令牌泄露: 如果 JWT 被盗(如 XSS、中间人攻击),攻击者可以在有效期内冒充用户(“持票攻击”)。缩短有效期和使用 HTTPS 是必须的。
      • 签名算法安全: 如果使用弱算法(如 HS256 密钥太弱)或实现不当(如未验证签名),可能被伪造。必须使用强算法(如 RS256ES256)并妥善保管私钥/密钥。
      • 敏感数据泄露: Payload 默认是 Base64 编码(可逆),不应在其中存放密码、信用卡号等绝对敏感信息。如需保密,应使用 JWE(JSON Web Encryption)进行加密。
    4. 客户端存储责任: 令牌由客户端(浏览器、移动 App)存储和管理,需要防范 XSS、CSRF 等攻击。
    5. 实现复杂度: 需要正确理解和实现签名/验证、密钥管理、声明处理、过期处理等,比生成随机字符串更复杂。
  • 典型使用场景:

    1. 跨域/单点登录: 用户在一个域登录后,可以获取一个 JWT,用于访问其他信任该 JWT 签发方的应用或服务。OAuth 2.0 / OpenID Connect 的核心令牌之一就是 JWT。
    2. API 认证与授权: 现代 RESTful / GraphQL API 的首选认证机制。客户端在登录后获取 JWT,后续请求在 Authorization: Bearer <token> 头中携带。API 服务器验证签名和声明即可判断身份和权限。
    3. 无状态微服务间通信: 微服务 A 可以将包含用户上下文的 JWT 传递给微服务 B,B 能独立验证并使用其中的信息,无需调用中心化的认证服务或共享会话存储。
    4. 信息交换: 作为在双方之间安全传递声明信息的一种方式(需签名/加密确保完整性和保密性),例如在 OAuth 流程中传递用户信息(ID Token)。

4.3 总结与选择建议

特性随机字符串 (无结构令牌)JWT (JSON Web Token)
核心引用 (指向服务器存储的数据)自包含 (数据在令牌内)
状态有状态 (服务器需存储会话)无状态 (服务器无需存储会话)
信息携带有 (Payload 中的声明)
验证方式查数据库/缓存验证签名/解密
性能每次请求需查存储 (可能成瓶颈)无存储查询 (签名验证计算开销小)
扩展性差 (需共享存储或粘性会话)极佳 (天然支持分布式)
撤销容易 (直接删除存储条目)困难 (需额外机制如黑名单、短有效期+Refresh)
大小较大
安全性依赖存储安全、传输安全;令牌本身无信息依赖算法强度、密钥管理、传输安全;需防泄露、篡改
复杂度低 (生成随机数、存、查)中高 (签名/验证、密钥管理、声明处理、安全最佳实践)
典型场景传统Web会话
一次性令牌
需即时撤销
API 认证
单点登录 / SSO
微服务通信

如何选择?

  1. 选择随机字符串 (无结构令牌) 当:

    • 你正在构建一个传统的、服务器端渲染的 Web 应用。
    • 你需要立即且可靠地撤销令牌的能力(如用户登出)。
    • 应用是单体或规模较小,维护共享会话存储不是问题。
    • 令牌本身不需要携带额外的声明信息。
    • 对性能要求极高且请求非常密集,且能承受存储查询开销(或有强大缓存)。
  2. 选择 JWT 当:

    • 你在构建 API(尤其是 RESTful / GraphQL)。
    • 你需要 SSO跨域/跨服务认证
    • 你的架构是 分布式、微服务,需要服务间传递用户上下文。
    • 可扩展性消除数据库依赖 是主要目标。
    • 令牌需要携带一些非绝对敏感的声明(用户ID、角色、权限),并让服务端能直接使用。
    • 你愿意并能够处理 JWT 的安全复杂性(签名、密钥管理、短有效期、HTTPS)和潜在的撤销难题。

重要安全提示:

  • 无论使用哪种方式,都必须通过 HTTPS 传输令牌!
  • JWT 的 Payload 不是加密的(除非使用 JWE),不要存敏感数据!
  • 使用强随机数生成器创建随机字符串或 JWT 的 jti (JWT ID)。
  • 仔细选择并安全配置 JWT 的签名算法和密钥。
  • 始终验证 JWT 的签名、有效期 (exp)、受众 (aud) 等关键声明。
  • 考虑令牌泄露的风险,使用较短的过期时间,并为 JWT 实现合理的撤销机制(如黑名单)或结合使用 Refresh Token。

在实践中,两者也并非完全互斥。例如,一个系统可能使用基于随机字符串的传统会话管理 Web 界面,而其后台 API 则使用 JWT 进行交互。或者,在 JWT 的流程中,Refresh Token 本身可能是一个存储在数据库中的随机字符串。理解各自的优缺点有助于你为系统的不同部分选择最合适的工具。

五、客户端传递Token

5.1 客户端使用HttpClient请求授权

5.2 客户端使用WebApiClient请求授权

5.3 客户端使用DmtpRpc请求授权

5.4 客户端使用通用Rpc请求授权

5.5 基于角色的授权