OAuth 简介 #

什么是授权? #

在了解 OAuth 之前,我们需要先理解"授权"的概念。授权(Authorization)是指授予某个主体访问特定资源的权限的过程。

text
┌─────────────────┐
│     用户         │
│  (资源所有者)    │
└────────┬────────┘
         │ 授权
         ▼
┌─────────────────┐
│   第三方应用     │
│  (客户端)       │
└────────┬────────┘
         │ 访问
         ▼
┌─────────────────┐
│   受保护资源     │
│  (资源服务器)    │
└─────────────────┘

认证 vs 授权 #

这是两个容易混淆的概念:

概念 英文 回答的问题 示例
认证 Authentication 你是谁? 登录验证身份
授权 Authorization 你能做什么? 获取访问权限
text
认证(Authentication):
"你是张三吗?" -> "是的,我是张三"

授权(Authorization):
"张三可以访问相册吗?" -> "可以,但只能读取"

什么是 OAuth? #

OAuth(Open Authorization,开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用。

核心定位 #

text
┌─────────────────────────────────────────────────────────────┐
│                         OAuth                                │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  安全授权    │  │  令牌机制    │  │  范围控制    │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  多种模式    │  │  刷新机制    │  │  标准协议    │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└─────────────────────────────────────────────────────────────┘

OAuth 解决的问题 #

传统方式的问题 #

在 OAuth 出现之前,第三方应用获取用户数据的方式:

text
┌─────────────────────────────────────────────────────────────┐
│                    传统密码共享模式                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   用户 ──── 用户名/密码 ────> 第三方应用                      │
│                                 │                           │
│                                 │ 使用密码登录               │
│                                 ▼                           │
│                            服务提供者                        │
│                                 │                           │
│                                 │ 返回数据                   │
│                                 ▼                           │
│                            第三方应用                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

问题:
❌ 用户密码暴露给第三方应用
❌ 第三方应用获得完全访问权限
❌ 无法限制访问范围
❌ 修改密码后所有第三方应用失效
❌ 无法单独撤销某个应用的访问权限

OAuth 的解决方案 #

text
┌─────────────────────────────────────────────────────────────┐
│                      OAuth 授权模式                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   用户 ──── 授权确认 ────> 服务提供者                         │
│    │                         │                              │
│    │                         │ 颁发令牌                      │
│    │                         ▼                              │
│    │                    第三方应用                           │
│    │                         │                              │
│    │                         │ 使用令牌访问                  │
│    │                         ▼                              │
│    └───────────────────> 服务提供者                          │
│                              │                              │
│                              │ 返回限定范围数据              │
│                              ▼                              │
│                         第三方应用                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

优势:
✅ 用户密码不暴露给第三方应用
✅ 可以限制访问范围(Scope)
✅ 可以随时撤销授权
✅ 令牌可以设置有效期
✅ 令牌泄露后影响有限

OAuth 的历史 #

发展历程 #

text
2006年 ─── OAuth 概念诞生
    │
    │      Blaine Cook 等人提出
    │      解决 Twitter API 授权问题
    │
2007年 ─── OAuth 1.0 发布
    │
    │      正式发布规范
    │      被广泛采用
    │
2010年 ─── OAuth 1.0a 发布
    │
    │      修复安全漏洞
    │      IETF RFC 5849
    │
2012年 ─── OAuth 2.0 发布
    │
    │      重新设计协议
    │      更简单更灵活
    │      IETF RFC 6749
    │
2015年 ─── OAuth 2.0 扩展
    │
    │      PKCE 扩展
    │      Token Revocation
    │
2020年 ─── OAuth 2.1 草案
    │
    │      整合最佳实践
    │      移除不安全特性
    │
至今   ─── 行业标准
    │
    │      几乎所有互联网服务
    │      身份认证基础设施

里程碑版本 #

版本 时间 RFC 重要特性
1.0 2007 - 初始版本,签名机制
1.0a 2010 5849 修复会话固定攻击
2.0 2012 6749 重新设计,多种授权模式
2.1 2021 草案 安全性增强,简化流程

OAuth 1.0 vs OAuth 2.0 #

主要区别 #

特性 OAuth 1.0 OAuth 2.0
复杂度 高(需要签名) 低(使用 HTTPS)
安全性 内置签名 依赖 TLS
授权模式 单一模式 多种模式
令牌类型 单一令牌 访问令牌 + 刷新令牌
移动端支持 困难 良好
扩展性 有限 良好

OAuth 2.0 的优势 #

text
┌─────────────────────────────────────────────────────────────┐
│                    OAuth 2.0 优势                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 更简单                                                   │
│     - 不需要复杂的签名计算                                    │
│     - 依赖 TLS 保证传输安全                                  │
│                                                             │
│  2. 更灵活                                                   │
│     - 多种授权模式适应不同场景                                │
│     - 可扩展的令牌格式                                       │
│                                                             │
│  3. 更安全                                                   │
│     - 访问令牌有效期短                                       │
│     - 刷新令牌可撤销                                        │
│     - 支持 PKCE 防止授权码劫持                               │
│                                                             │
│  4. 更广泛                                                   │
│     - 支持Web、移动端、桌面应用                              │
│     - 支持无用户参与的服务间调用                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

OAuth 的核心角色 #

四个核心角色 #

text
┌─────────────────────────────────────────────────────────────┐
│                     OAuth 核心角色                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌───────────────────┐                                      │
│  │ Resource Owner    │  资源所有者                          │
│  │ (资源所有者)       │  通常是指用户                        │
│  └───────────────────┘                                      │
│           │                                                 │
│           │ 授权                                            │
│           ▼                                                 │
│  ┌───────────────────┐      ┌───────────────────┐          │
│  │ Authorization     │      │ Resource Server   │          │
│  │ Server            │──────│ (资源服务器)       │          │
│  │ (授权服务器)       │ 令牌  │ 存储受保护资源     │          │
│  └───────────────────┘      └───────────────────┘          │
│           │                         ▲                       │
│           │ 授权码/令牌              │ 访问资源              │
│           ▼                         │                       │
│  ┌───────────────────┐              │                       │
│  │ Client            │──────────────┘                       │
│  │ (客户端)          │                                      │
│  │ 第三方应用        │                                      │
│  └───────────────────┘                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

角色详解 #

1. 资源所有者(Resource Owner) #

text
资源所有者是能够授予对受保护资源访问权限的实体。
通常是指用户(User)。

示例:
- Google 账户的用户
- GitHub 账户的用户
- 微信用户

2. 客户端(Client) #

text
客户端是代表资源所有者发起资源请求的应用程序。
即需要获取用户数据的第三方应用。

示例:
- 一个需要访问 Google 日历的应用
- 一个需要获取 GitHub 仓库信息的工具
- 一个需要读取微信用户信息的小程序

3. 授权服务器(Authorization Server) #

text
授权服务器在认证资源所有者并获得其授权后,颁发访问令牌。

示例:
- Google OAuth 2.0 服务器(accounts.google.com)
- GitHub OAuth 服务器(github.com/login/oauth)
- 微信开放平台授权服务器

4. 资源服务器(Resource Server) #

text
资源服务器托管受保护的资源,能够接受和响应
使用访问令牌对受保护资源的请求。

示例:
- Google Calendar API(calendar.googleapis.com)
- GitHub API(api.github.com)
- 微信 API(api.weixin.qq.com)

角色交互示例 #

text
场景:使用 Google 账号登录第三方应用

┌─────────┐     ┌─────────┐     ┌─────────┐     ┌─────────┐
│  用户   │     │ 第三方  │     │ Google  │     │ Google  │
│         │     │  应用   │     │ 授权服务│     │ 资源服务│
└────┬────┘     └────┬────┘     └────┬────┘     └────┬────┘
     │               │               │               │
     │ 1. 点击登录   │               │               │
     │──────────────>│               │               │
     │               │               │               │
     │               │ 2. 重定向到授权页面            │
     │<──────────────────────────────│               │
     │               │               │               │
     │ 3. 用户同意授权               │               │
     │──────────────────────────────>│               │
     │               │               │               │
     │               │ 4. 返回授权码 │               │
     │               │<──────────────│               │
     │               │               │               │
     │               │ 5. 用授权码换令牌              │
     │               │──────────────>│               │
     │               │               │               │
     │               │ 6. 返回访问令牌               │
     │               │<──────────────│               │
     │               │               │               │
     │               │ 7. 用令牌访问资源             │
     │               │──────────────────────────────>│
     │               │               │               │
     │               │ 8. 返回用户数据               │
     │               │<──────────────────────────────│
     │               │               │               │
     │ 9. 登录成功   │               │               │
     │<──────────────│               │               │
     │               │               │               │

OAuth 的核心概念 #

访问令牌(Access Token) #

text
访问令牌是用于访问受保护资源的凭证。

特点:
- 由授权服务器颁发
- 有一定的有效期
- 代表用户授予的权限范围
- 可以是任意格式(通常使用 JWT)

示例:
{
  "access_token": "ya29.a0AfH6SMBx...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "1//0g...",
  "scope": "profile email"
}

刷新令牌(Refresh Token) #

text
刷新令牌用于获取新的访问令牌。

特点:
- 有效期通常比访问令牌长
- 可以多次使用
- 可以被撤销
- 不直接用于访问资源

使用场景:
- 访问令牌过期后获取新令牌
- 长期访问用户资源
- 减少用户重复授权

授权范围(Scope) #

text
Scope 用于限制令牌的访问权限范围。

示例:
- profile:访问基本信息
- email:访问邮箱地址
- openid:身份认证
- https://www.googleapis.com/auth/calendar:访问日历

请求多个 Scope:
scope=profile%20email%20openid

作用:
✅ 最小权限原则
✅ 用户知情权
✅ 安全隔离

授权码(Authorization Code) #

text
授权码是授权流程中的临时凭证。

特点:
- 一次性使用
- 有效期短(通常几分钟)
- 与 redirect_uri 绑定
- 需要客户端认证

作用:
- 防止令牌直接暴露给前端
- 增加安全性

OAuth 2.0 授权模式概览 #

四种主要授权模式 #

text
┌─────────────────────────────────────────────────────────────┐
│                   OAuth 2.0 授权模式                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 1. 授权码模式(Authorization Code)                   │   │
│  │    - 最安全、最完整                                   │   │
│  │    - 适用于服务器端应用                               │   │
│  │    - 推荐使用                                         │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 2. 简化模式(Implicit)                               │   │
│  │    - 适用于纯前端应用                                 │   │
│  │    - 已不推荐使用                                     │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 3. 密码模式(Resource Owner Password Credentials)   │   │
│  │    - 用户密码直接换取令牌                             │   │
│  │    - 仅限高度信任场景                                 │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 4. 客户端凭证模式(Client Credentials)               │   │
│  │    - 无用户参与                                       │   │
│  │    - 适用于服务间通信                                 │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

模式选择指南 #

场景 推荐模式 原因
Web 服务器应用 授权码模式 安全性最高
单页应用(SPA) 授权码 + PKCE 防止授权码泄露
原生移动应用 授权码 + PKCE 安全性保障
服务间通信 客户端凭证 无需用户参与
第一方应用 密码模式(谨慎使用) 高度信任场景

OAuth 的应用场景 #

1. 第三方登录 #

text
"使用 Google 登录"
"使用微信登录"
"使用 GitHub 登录"

优势:
- 用户无需注册新账号
- 简化登录流程
- 提高转化率

2. API 授权 #

text
应用需要访问用户的:
- Google 日历
- GitHub 仓库
- 微信朋友圈
- 微博发布

优势:
- 用户控制授权范围
- 可随时撤销
- 安全可控

3. 企业应用集成 #

text
企业内部系统集成:
- 单点登录(SSO)
- 跨系统授权
- 统一身份管理

优势:
- 集中管理
- 安全合规
- 审计追踪

4. IoT 设备授权 #

text
智能家居设备:
- 智能音箱访问音乐服务
- 智能电视访问视频平台
- 智能家居控制

优势:
- 设备安全授权
- 用户可控
- 令牌管理

OAuth 与 OpenID Connect #

关系说明 #

text
┌─────────────────────────────────────────────────────────────┐
│                    OAuth vs OIDC                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   OAuth 2.0:授权协议                                        │
│   - 解决"授权"问题                                          │
│   - "这个应用能访问你的数据吗?"                             │
│                                                             │
│   OpenID Connect:身份认证协议                               │
│   - 基于OAuth 2.0构建                                       │
│   - 解决"认证"问题                                          │
│   - "你是谁?"                                              │
│                                                             │
│   关系:                                                     │
│   OIDC = OAuth 2.0 + ID Token + UserInfo Endpoint           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

OAuth 的安全性 #

主要安全威胁 #

text
┌─────────────────────────────────────────────────────────────┐
│                    OAuth 安全威胁                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 授权码劫持                                               │
│     - 攻击者截获授权码                                       │
│     - 解决方案:PKCE 扩展                                    │
│                                                             │
│  2. 令牌泄露                                                 │
│     - 令牌被窃取                                            │
│     - 解决方案:短有效期 + 安全存储                          │
│                                                             │
│  3. CSRF 攻击                                                │
│     - 伪造授权请求                                          │
│     - 解决方案:state 参数                                   │
│                                                             │
│  4. 开放重定向                                               │
│     - redirect_uri 验证不严                                 │
│     - 解决方案:严格白名单                                   │
│                                                             │
│  5. 混淆攻击                                                 │
│     - 不同类型令牌混用                                       │
│     - 解决方案:严格区分令牌类型                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

安全最佳实践 #

text
1. 始终使用 HTTPS
2. 使用 state 参数防止 CSRF
3. 严格验证 redirect_uri
4. 使用 PKCE(对于公共客户端)
5. 访问令牌使用短有效期
6. 安全存储令牌
7. 实现令牌撤销机制

OAuth 的优势与局限 #

优势 #

text
✅ 安全性高
   - 用户密码不暴露给第三方
   - 令牌可撤销
   - 可限制访问范围

✅ 用户体验好
   - 无需记忆多个密码
   - 一键授权
   - 统一身份

✅ 标准化
   - 行业标准协议
   - 丰富的库和工具
   - 广泛支持

✅ 灵活性
   - 多种授权模式
   - 可扩展
   - 适应各种场景

局限性 #

text
⚠️ 复杂性
   - 协议概念较多
   - 实现细节复杂
   - 需要理解安全概念

⚠️ 依赖 HTTPS
   - OAuth 2.0 安全依赖 TLS
   - 需要正确配置证书

⚠️ 令牌管理
   - 需要安全存储令牌
   - 需要处理令牌过期
   - 需要实现刷新逻辑

⚠️ 服务端要求
   - 需要授权服务器
   - 需要维护用户会话

学习路径 #

text
入门阶段
├── OAuth 简介(本文)
├── 核心概念
└── 授权码模式

进阶阶段
├── 其他授权模式
├── PKCE 扩展
├── JWT 与 OAuth
└── OpenID Connect

高级阶段
├── 安全最佳实践
├── 高级主题
├── 常见问题解决
└── 实战案例

下一步 #

现在你已经了解了 OAuth 的基本概念,接下来学习 核心概念,深入了解 OAuth 的各个组成部分!

最后更新:2026-03-28