# 一、参考文献

  Oauth 是一个关于授权的开发网络标准:

参考资料 RFC 6749 (opens new window) (可以直接在下面的【RFC 6749】查看)

# 1、理解 OAuth 2.0

参考文章

理解 OAuth 2.0 (opens new window)
OAuth 2.0 的一个简单解释 (opens new window)

参考视频

授权第三方比比机制 (opens new window)

# 2、使用 OAuth 2.0

OAuth 2.0 的四种方式 (opens new window)
GitHub OAuth 第三方登录示例教程 (opens new window)

# 三、授权码模式 ✨

理解

微信授权登录

# 1、执行流程

官方文档 (opens new window)

# 示意图

 +----------+
 |   用户   |
 +----------+
      ^
      |
     (B)
 +----|-----+          Client Identifier      +---------------+
 |         -+----(A)-- & Redirection URI ---->|               |
 |  User-   |                                 |     微信      |
 |  Agent  -+----(B)-- User authenticates --->|  授权服务器   |
 |          |                                 |               |
 |         -+----(C)-- Authorization Code ---<|               |
 +-|----|---+                                 +---------------+
   |    |                                         ^      v
  (A)  (C)                                        |      |
   |    |                                         |      |
   ^    v                                         |      |
 +---------+                                      |      |
 |         |>---(D)-- Authorization Code ---------'      |
 |第三方应用|          & Redirection URI                  |
 |         |                                             |
 |         |<---(E)----- Access Token -------------------'
 +---------+       (w/ Optional Refresh Token)

# 流程介绍

  • A:第三方应用通过浏览器(User-Agent)给用户提供一个‘微信登录’链接,用户点击跳转到微信授权服务器
  • B:用户根据微信授权服务器提示登录微信并确认授权给 第三方应用
  • C:微信授权服务器向浏览器(User-Agent)返回一个授权码,浏览器(User-Agent)再把授权码给第三方应用
  • D:第三方应用此时凭借授权码向微信授权服务器发起一个获取令牌请求。

然后,第三方应用 就可以携带令牌向微信读取用户资料了。

# 2、获取授权码(在前端)

  • 第三方应用 网站

https://client.example.com/

  • A:通过弹窗扫一扫 / 页面跳转 进入 微信授权页面

(前端可以对该 url 进行 ✍ 配置)
https://open.weixin.qq.com/connect/oauth2/authorize?

response_type=code& 必填 - 固定的
client_id=s6BhdRkqt3& 必填 - 请求者身份 id(公司微信开发者账号)
redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb 设置重定向地址 /cb

state=xyz

  • B:用户在微信授权页面同意 第三方应用 可以获取他的微信昵称、头像等

  • C:微信授权页面 重定向 到设置的重定向地址(并携带了授权码 code)

页面自动跳转地址
https://client.example.com/cb? 重定向到设置的地址

code=SplxlOBeZQQYbYS6WxSbIA& 响应 授权码 code

state=xyz

# 3、换取令牌(向后端)

  • D:这时 第三方应用 凭借授权码,可以向微信授权服务器发起请求获取令牌 access_token

发起 POST 请求
https://api.weixin.qq.com/sns/oauth2/access_token? 重定向到设置的地址

grant_type=authorization_code& 必填 - 固定的
client_id=s6BhdRkqt3& 必填 - 请求者身份 id(公司微信开发者账号)
code=SplxlOBeZQQYbYS6WxSbIA& 必填 - 授权码
redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb 前面设置的重定向地址 /cb

  • E:微信授权服务器返回一个 JSON 字符串(携带了令牌 access_token)
{
  "access_token":"ACCESS_TOKEN",
  "token_type":"bearer",
  "expires_in":2592000,
  "refresh_token":"REFRESH_TOKEN",
  "scope":"read",
  "uid":100101,
  "info":{...}
}

# 4、更新令牌

  当令牌到期时,OAuth 2.0 允许用户自动更新令牌。具体操作就是我们使用 refresh token 发一个请求,去更新令牌

  • 直接使用 微信授权服务器返回的 refresh_token

发起 POST 请求 https://api.weixin.qq.com/sns/oauth2/access_token? 重定向到设置的地址

grant_type=refresh_token& 必填 - 固定的
client_id=s6BhdRkqt3& 必填 - 请求者身份 id(公司微信开发者账号)
refresh_token=Y6dGdRka5b 必填

# 4、开发应用 ✍

  授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。

使用文档:

微信网站应用授权 (opens new window)
微信移动应用授权 (opens new window)

QQ 网站应用授权 (opens new window)

经典使用 👀:

easydoc 登录页 (opens new window)

代码实现:

github 授权登录模拟
easydoc 登录页模拟

# 四、密码模式

理解

微信账号登录

# 1、执行流程

官方文档 (opens new window)

# 示意图

 +----------+
 |   用户   |
 +----------+
      v
      |    Resource Owner
     (A) Password Credentials
      |
      v
 +---------+                                  +---------------+
 |         |>--(B)---- Resource Owner ------->|               |
 |         |         Password Credentials     |     微信      |
 |第三方应用|                                   |  授权服务器   |
 |         |<--(C)---- Access Token ---------<|               |
 |         |    (w/ Optional Refresh Token)   |               |
 +---------+                                  +---------------+

# 2、开发应用

  • A:用户直接在第三方应用中告诉直接微信的用户名和密码。
  • B:哔哔哩哔直接凭借用户提供的用户名和密码向微信授权服务器发起一个获取令牌请求。

发起 POST 请求 https://api.weixin.qq.com/sns/oauth2/access_token? 重定向到设置的地址

grant_type=password& 必填 - 固定的
username=s6BhdRkqt3& 必填 - 微信用户名
password=SplxlOBeZQQYbYS6WxSbIA& 必填 - 微信密码

  • C:微信授权服务器返回一个 JSON 字符串(携带了令牌 access_token)

# 五、客户端模式

理解

第三方应用 发布更新公告(直接向微信授权服务器获取所有粉丝账号的 openId)

# 1、执行流程

官方文档 (opens new window)

# 示意图

 +---------+                                  +---------------+
 |         |                                  |               |
 |         |>--(A)- Client Authentication --->|     微信      |
 |第三方应用|                                   |  授权服务器   |
 |         |<--(B)---- Access Token ---------<|               |
 |         |                                  |               |
 +---------+                                  +---------------+

# 2、开发应用

  • A:哔哔哩哔直接向微信授权服务器发起一个获取令牌请求。

发起 POST 请求 https://api.weixin.qq.com/sns/oauth2/access_token? 重定向到设置的地址

grant_type=client_credentials& 必填 - 固定的
client_id=s6BhdRkqt3& 必填 - 请求者身份 id(公司微信开发者账号)
client_secret=SplxlOBeZQQYbYS6WxSbIA& 必填 - 账号密码

  • C:微信授权服务器返回一个 JSON 字符串(携带了令牌 access_token)

# 六、隐藏模式

  这个和授权码模式非常相似,只不过它直接允许在前端 获取令牌 access_token。(显然,这种直接将令牌暴露在前端是非常不安全的。)

# 使用流程

  • 第三方应用 网站

https://client.example.com/

  • A:通过弹窗扫一扫 / 页面跳转 进入 微信授权页面

(前端可以对该 url 进行配置) https://open.weixin.qq.com/connect/oauth2/authorize?

response_type=token& 必填 - 固定的
client_id=s6BhdRkqt3& 必填 - 请求者身份 id(公司微信开发者账号)
redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb 设置重定向地址 /cb

state=xyz

  • B:用户在微信授权页面同意 第三方应用 可以获取他的微信昵称、头像等

  • C:微信授权页面 ✨ 重定向到设置的重定向地址(直接携带了令牌 access_token )

页面自动跳转地址 https://client.example.com/cb# 重定向到设置的地址

token=SplxlOBeZQQYbYS6WxSbIA& 响应 令牌 access_token

state=xyz

注意

  还要注意的一个细节是,这部分返回的令牌的位置在 URL 锚点上,而不是查询字符串上。

# 七、答疑解惑 ✨

  • client_id 是怎么获取的?

在进行操作前 第三方应用 要在授权服务器那注册,然后授权服务器就会给 第三方应用 分配两个身份识别码:

  • 微信开放平台的 appid --- 对应 client_id
  • 微信开放平台的 appsecret --- 对应 client_secret
  • 常用的授权服务器地址在哪里申请?

github 登记 (opens new window)
微信 登记 (opens new window) ---> 测试账号获取 (opens new window)
QQ 登记 (opens new window)

  • 授权服务器存在的意义是什么?

可以减少用户手动注册账号的概率。想一想,如果我们在登录任何一个网站,都可以通过 qq、微信、微博等授权服务器进行登录,即免去了注册过程,网站又获取了用户基本信息。

更新于 : 8/7/2024, 2:16:31 PM