OAuth2四种授权流程:哪种适合你的App?

OAuth2四种授权流程:哪种适合你的App?

OAuth2授权流程

引言:选择困难症的解药

OAuth2有四种授权流程,每种都有不同的适用场景。

如果你是开发者,可能会纠结:我的App该用哪种流程?

今天,我用最白话的方式,给你讲明白这四种流程的区别。

第一章:授权码流程(最常用)

一句话解释

就像去银行取钱:先拿号,再取钱。

流程比喻

想象你去银行取钱:

  1. :我要取钱
  2. 银行:好的,给你一个号(授权码)
  3. :拿着号去柜台
  4. 银行:验证号,给你钱(访问令牌)

技术流程

1
2
3
4
5
6
7
8
9
10
11
用户 → 点击"微信登录"

App → 跳转到微信授权页面

微信 → 显示授权页面,用户确认

微信 → 返回授权码给App

App → 用授权码换访问令牌

App → 用访问令牌获取用户信息

适用场景

  • Web应用:有后端服务器
  • 移动App:原生应用
  • 单页应用:需要安全存储令牌

安全优势

  • 令牌不经过浏览器
  • 支持刷新令牌
  • 可以验证客户端身份

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1. 生成授权链接
auth_url = "https://wechat.com/oauth2/authorize?" + \
"client_id=YOUR_CLIENT_ID&" + \
"redirect_uri=https://your-app.com/callback&" + \
"response_type=code&" + \
"scope=snsapi_userinfo"

# 2. 用户授权后,获取授权码
code = request.args.get('code')

# 3. 用授权码换令牌
token_url = "https://wechat.com/oauth2/token"
data = {
'grant_type': 'authorization_code',
'code': code,
'client_id': 'YOUR_CLIENT_ID',
'client_secret': 'YOUR_CLIENT_SECRET',
'redirect_uri': 'https://your-app.com/callback'
}
response = requests.post(token_url, data=data)
access_token = response.json()['access_token']

第二章:隐式流程(已废弃)

一句话解释

就像快餐店点餐:直接给你餐,不用排队。

流程比喻

想象你去快餐店:

  1. :我要一个汉堡
  2. 快餐店:好的,直接给你汉堡(访问令牌)
  3. :拿着汉堡走人

技术流程

1
2
3
4
5
6
7
用户 → 点击"登录"

App → 跳转到授权页面

授权服务器 → 直接返回访问令牌(在URL中)

App → 从URL中提取令牌

为什么废弃?

安全问题

  • 令牌暴露在URL中
  • 可能被浏览器历史记录
  • 可能被中间人攻击

替代方案

现在推荐使用授权码流程 + PKCE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 生成随机码验证器
code_verifier = generate_random_string(128)
code_challenge = base64url_encode(sha256(code_verifier))

# 授权请求中添加挑战
auth_url = "https://example.com/oauth2/authorize?" + \
"code_challenge=" + code_challenge + "&" + \
"code_challenge_method=S256"

# 令牌请求中添加验证器
data = {
'code_verifier': code_verifier,
'code': code,
...
}

第三章:客户端凭证流程

一句话解释

就像公司内部调用:员工之间直接沟通,不用经过前台。

流程比喻

想象公司内部:

  1. 员工A:我需要销售数据
  2. 员工B:好的,给你(访问令牌)
  3. 员工A:拿着令牌去数据库

技术流程

1
2
3
4
5
客户端 → 直接向授权服务器请求令牌

授权服务器 → 验证客户端身份,返回令牌

客户端 → 用令牌访问资源

适用场景

  • 服务间通信:微服务架构
  • 后台任务:定时任务
  • 机器对机器:没有用户参与

代码示例

1
2
3
4
5
6
7
8
9
10
# 直接用客户端ID和密钥换令牌
token_url = "https://api.example.com/oauth2/token"
data = {
'grant_type': 'client_credentials',
'client_id': 'YOUR_CLIENT_ID',
'client_secret': 'YOUR_CLIENT_SECRET',
'scope': 'read write'
}
response = requests.post(token_url, data=data)
access_token = response.json()['access_token']

安全考量

  • 客户端密钥必须安全存储
  • 只用于服务间通信
  • 不要暴露给前端

第四章:设备授权流程

一句话解释

就像电视扫码登录:电视显示二维码,你用手机扫码确认。

流程比喻

想象你用电视登录:

  1. 电视:显示二维码
  2. :用手机扫码
  3. 手机:确认授权
  4. 电视:获得访问令牌

技术流程

1
2
3
4
5
6
7
8
9
设备 → 请求设备码

授权服务器 → 返回设备码和用户码

设备 → 显示二维码(包含用户码)

用户 → 用手机扫码,确认授权

设备 → 轮询授权服务器,获取令牌

适用场景

  • 智能电视:没有键盘
  • 游戏机:输入不便
  • IoT设备:屏幕小

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 1. 请求设备码
device_code_url = "https://example.com/oauth2/device/code"
data = {
'client_id': 'YOUR_CLIENT_ID',
'scope': 'read write'
}
response = requests.post(device_code_url, data=data)
device_code = response.json()['device_code']
user_code = response.json()['user_code']
verification_uri = response.json()['verification_uri']

# 2. 显示二维码
print(f"请访问 {verification_uri} 并输入 {user_code}")

# 3. 轮询获取令牌
while True:
token_url = "https://example.com/oauth2/token"
data = {
'grant_type': 'urn:ietf:params:oauth:grant-type:device_code',
'device_code': device_code,
'client_id': 'YOUR_CLIENT_ID'
}
response = requests.post(token_url, data=data)

if response.status_code == 200:
access_token = response.json()['access_token']
break

time.sleep(5)

第五章:如何选择?

选择指南

场景 推荐流程 原因
Web应用(有后端) 授权码流程 最安全
单页应用(SPA) 授权码+PKCE 安全且简单
移动App 授权码+PKCE 安全且原生支持
服务间通信 客户端凭证 无用户参与
智能设备 设备授权 输入不便
遗留系统 隐式流程 已废弃,不推荐

决策树

1
2
3
4
5
你的App有用户参与吗?
├── 是 → 用户能方便输入吗?
│ ├── 是 → 授权码流程
│ └── 否 → 设备授权流程
└── 否 → 客户端凭证流程

第六章:实战建议

开发者清单

  • 确定你的App类型
  • 选择合适的授权流程
  • 实现令牌存储
  • 实现令牌刷新
  • 实现错误处理
  • 测试各种场景

常见错误

  1. 使用隐式流程:已废弃,不要用
  2. 不验证重定向URI:可能导致令牌泄露
  3. 令牌存储不安全:可能被窃取
  4. 不处理令牌过期:用户体验差

总结

核心要点

  1. 授权码流程:最常用,最安全
  2. 隐式流程:已废弃,不要用
  3. 客户端凭证:服务间通信
  4. 设备授权:输入不便的设备

选择建议

  • 大多数场景:使用授权码流程
  • 单页应用:授权码 + PKCE
  • 服务间通信:客户端凭证
  • 智能设备:设备授权

给开发者的建议

  • 不要自己发明轮子:使用成熟的OAuth2库
  • 遵循最佳实践:参考RFC和官方文档
  • 安全第一:令牌存储和传输必须安全
  • 测试充分:各种场景都要测试

选择正确的OAuth2流程,就像选择正确的交通工具:选对了,事半功倍。