本文目录导读:

OAuth2授权码模式(Authorization Code Grant)是功能最完整、流程最严密的授权模式,也是目前最常用、最推荐的授权方式,尤其适用于有后端的Web应用。
它引入了一个中间人(授权码),避免了敏感信息(如密码或长期令牌)直接暴露在用户浏览器或第三方客户端。
核心角色
- 资源所有者:你(用户)。
- 客户端:想要访问你数据的第三方应用(如“用微信登录某网站”中的那个网站)。
- 授权服务器:负责认证用户身份并颁发授权码和令牌(如微信的认证服务器)。
- 资源服务器:存储用户受保护数据的服务器(如微信的用户信息API)。
授权码模式的工作流程(以“用微信登录某网站”为例)
这是最经典的、基于两次重定向的流程:
sequenceDiagram
participant User as 用户(浏览器)
participant Client as 第三方网站(客户端)
participant Auth as 微信授权服务器
participant API as 微信资源服务器
User->>Client: 1. 点击“微信登录”
Client->>User: 2. 重定向到微信授权页(附带ClientID、RedirectURI)
User->>Auth: 3. 用户确认授权
Auth->>User: 4. 重定向回第三方网站(附带授权码)
User->>Client: 5. 将授权码发给第三方网站后端
Client->>Auth: 6. 用授权码 + ClientSecret 换取 Access Token
Auth->>Client: 7. 返回 Access Token(可能还有 Refresh Token)
Client->>API: 8. 使用 Access Token 请求用户信息
API->>Client: 9. 返回用户数据(如昵称、头像)
Client->>User: 10. 登录成功,展示用户信息
步骤详细拆解:
-
发起请求:用户在第三方网站点击“微信登录”,网站将用户重定向到微信的授权页面。
- URL参数包含:
response_type=code(告诉授权服务器,我要授权码)client_id(第三方网站自己的ID)redirect_uri(授权成功后的回调地址)scope(请求的权限范围)state(防CSRF攻击的随机字符串)
- URL参数包含:
-
用户认证并授权:用户在微信页面输入账号密码,确认授权(是否允许该网站获取头像昵称)。
-
颁发授权码:微信授权服务器将用户重定向回
redirect_uri,并在URL的查询参数中附上授权码(code)。https://example.com/callback?code=ABC123&state=xyz -
后端兑换令牌:第三方网站的后端服务器收到这个授权码后,现在直接与微信授权服务器通信(不再是浏览器)。
- 请求参数:
grant_type=authorization_codecode(上一步得到的授权码)client_id(第三方网站的ID)client_secret(第三方网站的密钥,非常重要!)redirect_uri(必须与第一步一致,验证完整性)
- 请求参数:
-
颁发访问令牌:微信授权服务器验证
client_secret和授权码后,返回访问令牌(Access Token)。 -
获取资源:第三方网站后端拿着Access Token去请求微信资源服务器,获取用户信息(如昵称、头像)。
为什么需要“授权码”这个中间步骤? (核心优势)
这是授权码模式最精妙的设计:安全性 + 隔离
- 避免令牌暴露:如果不使用授权码,而是浏览器在第一步直接拿到Access Token:
- 那这个令牌会出现在浏览器的地址栏(HTTP Referer头容易被泄露)。
- 浏览器环境中的恶意脚本(XSS攻击)可以直接窃取令牌。
- 双重认证:
- 授权码(code)是临时、一次性的(通常几分钟有效)。
- 客户端可以用
client_secret在后端安全地兑换令牌。 - 即使授权码被中间人截获,由于他没有
client_secret,也无法交换到Access Token。
- 长期刷新能力:授权码模式颁发的Access Token有效期较短(如1小时),同时会附带一个Refresh Token,允许客户端在令牌过期后,在后端静默地刷新令牌,无需用户再次操作。
PKCE 扩展:更安全的授权码模式
对于没有后端的客户端(如原生App、纯前端单页应用),client_secret无法安全存储,为了提升安全性,OAuth2.0引入了PKCE(Proof Key for Code Exchange,代码交换证明密钥) 扩展。
原理:
- 客户端在请求授权码时,生成一个随机字符串
code_verifier(代码验证器),并计算其哈希值code_challenge(代码挑战值)一起发送给授权服务器。 - 授权服务器返回授权码时,会记住
code_challenge。 - 在兑换令牌时,客户端必须提供原始的
code_verifier。 - 授权服务器验证收到的
code_verifier是否与之前保存的code_challenge匹配。
好处:即使授权码被截获,由于攻击者不知道code_verifier,他依然无法用授权码成功兑换令牌,这被称为授权码拦截攻击(Authorization Code Interception Attack) 的终结者。
何时使用授权码模式?
| 场景 | 是否推荐 | 原因 |
|---|---|---|
| 经典Web应用 (有后端服务器) | ✅ 强烈推荐 | 后端可安全保存client_secret,流程最完整。 |
| 原生移动App | ✅ 推荐(使用PKCE) | 虽然无法安全保存client_secret,但PKCE提供了接近同等级别的安全保障。 |
| 单页应用(SPA) | ✅ 推荐(使用PKCE) | 纯前端无法安全保存client_secret,PKCE是标准答案,复杂场景建议使用后端反向代理(BFF,Backend For Frontend)模式。 |
| 客户端凭证模式 | ❌ 不应使用 | 该模式服务于服务器之间的通信(无用户参与),授权码模式不适用。 |
一句话总结:授权码模式通过引入一次性、短时效的授权码,以及在后端使用client_secret兑换令牌,将用户、客户端和令牌三者隔离,从根本上防止了令牌在不可信的前端环境中被泄露的风险,它是构建安全授权流程的黄金标准。