Skip to content

如何设计一个 OAuth2.0 授权服务?Token 如何管理? ​

  • 标签:后端、场景题、系统设计

🏛 业务架构师 ​

设计 OAuth2.0 授权服务,我先点破它的业务本质:OAuth2.0 是开放生态的信任基础设施——让第三方应用在用户授权下安全访问用户数据,而不交出密码。设计目标不仅是技术安全,还有生态治理能力(谁有权接什么、接了多少、如何计费审计)。

授权流程:授权码模式(标准答案)

第三方应用 → 引导用户跳转授权页(?client_id&scope&redirect_uri&state)
用户确认 → 重定向回 redirect_uri 带code(一次性, 5分钟有效)
第三方后端用 code + client_secret 换 access_token
API 调用带 access_token

为什么用授权码:code 换 token 的动作发生在后端(secret 不暴露)、code 一次性可撤销、防 token 经浏览器泄漏。SPA/移动端用 PKCE 变体。

Token 管理(题眼)

  • access_token 短效(2 小时)+ refresh_token 长效(30 天,可撤销),JWT 格式便于网关本地验签
  • refresh 轮换 + 失效检测(同一 refresh 二次使用 = 泄漏信号,作废全家)
  • scope 最小化授权:第三方只能申请具体权限(只读头像),不是全账户——权限粒度是数据安全的边界
  • 撤销机制:用户可随时在"授权管理"页解除第三方授权,token 立即失效——这是合规要求也是用户信任的基础

平台治理(架构师差异点)

  • 第三方应用准入审核、应用分级(不同级别不同配额)
  • 配额与计费:按 app 限流、调用量统计——开放平台是生意,计量是收入基础
  • 审计合规:完整授权日志、数据访问日志(谁、何时、取了什么),满足监管审查
  • redirect_uri 白名单严格校验(防授权码劫持)

收尾:授权服务的 SLA 要求极高(它挂 = 整个生态瘫痪),必须多活部署 + 全链路监控。

🏗 系统架构师 ​

设计 OAuth2.0 授权服务,我先定角色与流程,再讲 Token 管理与安全加固。

1. 核心角色与四种授权模式选型 资源所有者(用户)、客户端(第三方应用)、授权服务器、资源服务器。模式选型:

  • 授权码模式(最常用):Web 应用三方登录,带 PKCE 防截获,公开客户端必配
  • 客户端凭证模式:服务间调用(machine to machine)
  • 密码模式与隐式模式已不推荐(OAuth 2.1 移除)

2. 授权码流程实现要点(以三方登录为例)

text
1) 客户端重定向用户到 /authorize?client_id&redirect_uri&scope&state&code_challenge
2) 用户登录并授权,服务端校验 client 的 redirect_uri 白名单(防钓鱼)
3) 生成一次性 code(TTL 5分钟,绑定 client_id+用户+redirect_uri),302 回传
4) 客户端后端拿 code + code_verifier 换 token
5) 验证通过签发 access_token + refresh_token

要点:code 一次性使用(用过即焚,防重放)、state 参数防 CSRF、PKCE 的 S256 校验。

3. Token 管理(题眼)

  • access_token 用 JWT:payload 含 sub(用户)、client_id、scope、exp(15分钟~2小时)、jti;RS256 签名,资源服务用公钥本地验签,免查库
  • refresh_token 管理:长效(7~30天)且必须可撤销——存 Redis(userId+clientId 维度),支持旋转:每次刷新发新 refresh_token 并作废旧值,检测到旧值被复用判定泄露,撤销整个 token 家族
  • 吊销:改密/风控时按用户撤销:JWT 配黑名单(jti 或 userId+签发时间版本,TTL=剩余有效期)
  • JWKS 端点暴露公钥,支持密钥轮换(kid 区分多把钥匙,新旧并行期平滑过渡)

4. 安全与运维:client_secret 只存服务端、全链路 TLS、授权页防点击劫持、审计日志(谁授权了什么 scope)、限流防暴力枚举。

💻 全栈开发专家 ​

我基于 OAuth2.1 实践讲:授权码模式为核心,Token 管理是重心。

授权服务核心流程(授权码 + PKCE)

1. 客户端引导用户: GET /authorize?response_type=code&client_id=xx
   &redirect_uri=xx&scope=xx&state=xx&code_challenge=sha256(...)
2. 用户登录认证中心 -> 授权 -> 302 回 redirect_uri?code=xxx(code 5分钟有效、一次性)
3. 客户端后端换 token:
   POST /token  grant_type=authorization_code&code=xxx&code_verifier=xxx
4. 返回 access_token(refresh_token)

PKCE 必须(公开客户端防 code 截获),state 防 CSRF。授权码模式的意义:密码不经过第三方应用。

Token 管理

  • access token:短命(15 分钟~2 小时)。形态二选一:
    • JWT:资源服务本地验签,无网络开销;代价是撤销难。
    • opaque + Redis:可控可撤销,适合内部统一网关。 我的生产选择:JWT + 会话撤销表(登出/踢人写黑名单,TTL=剩余有效期)。
  • refresh token:长命(7~30 天),旋转(rotation)——每次刷新发新 refresh token 并作废旧值,检测到旧值被复用说明泄露,立即吊销整条 token 家族。
  • jti + aud/iss/scope 校验:防止跨系统串用。

实现

直接用 Spring Authorization Server(官方继任者),过滤器链开箱即用;自研踩坑成本极高(安全细节:重定向 URI 白名单严格校验、code 一次性、防暴力枚举限流)。