为了防止自己以后忘记/搞混 OAuth 流程, 写此文章.

OAuth作用

OAuth设计的目的是安全的向第三方应用提供用户的数据

在 OAuth 中, 有三种角色:

  • 资源服务器
  • 授权服务器
  • 用户(用户代理)

关于 OAuth2.0 安全性你应该要知道的一些事

OAuth流程

授权码

这是应用最广泛的方式
用户点击本地应用中的 第三方登录/授权.

https://third.com/oauth/authorize? //应用访问第三方网址
  response_type=code& //表示授权码方式
  client_id=CLIENT_ID& //表明应用身份
  redirect_uri=CALLBACK_URL& //回调
  scope=read //请求的权限

第三方服务器要求用户登录, 成功后跳转 CALLBACK_URL(本地应用构造的地址) 并携带 授权码.
此时帐号密码是在第三方服务器完成的, 应用不可能获取到.

https://app.com/callback? //302跳转
  code=AUTHORIZATION_CODE //授权码

本地应用拿到授权码后, 访问应用后端服务器, 后端服务器再携带 AUTHORIZATION_CODE 和 CLIENT_SECRET 访问第三方服务器.
此时本地应用不能获得 CLIENT_SECRET, 就无法伪造后端服务器身份.

https://third.com/oauth/token? //
  client_id=CLIENT_ID& //表明应用身份
  client_secret=CLIENT_SECRET& //证明应用身份
  grant_type=authorization_code& //表示要获取Token
  code=AUTHORIZATION_CODE& //授权码
  redirect_uri=CALLBACK_URL //回调

第三方服务器验证 CLIENT_ID/CLIENT_SECRET/AUTHORIZATION_CODE 并向 CALLBACK_URL 发送一段Json数据.

{    
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
}

此时应用后端服务器就获得了Token ,就可以携带Token访问资源服务器了.
本地应用再向应用后端服务器拉取数据即可.

隐藏式

https://third.com/oauth/authorize? //应用访问第三方网址
  response_type=code& //表示隐藏方式
  client_id=CLIENT_ID& //表明应用身份
  redirect_uri=CALLBACK_URL& //回调
  scope=read //请求的权限

第三方服务器要求用户登录, 成功后跳转 CALLBACK_URL(本地应用构造的地址) 并携带 授权码.

https://app.com/callback#token=ACCESS_TOKEN //注意参数不是?,而是#

可以注意到应用无法证明自己的身份(CLIENT_SECRET), 可以由其他人伪造, 所以该方法并不安全.

密码式

https://third.com/token? //应用访问第三方网址
  grant_type=password& //表示隐藏方式
  username=USERNAME& //账号
  password=PASSWORD& //密码
  client_id=CLIENT_ID //表明应用身份

第三方服务器要求用户登录, 成功后直接返回Json.
这个方法需要帐号密码, 且还是无法证明应用身份, 也不是很安全.

凭证式

https://third.com/token? //应用访问第三方网址
  grant_type=client_credentials& //表示凭证式
  client_id=CLIENT_ID& //表明应用身份
  client_secret=CLIENT_SECRET //证明应用身份

第三方服务器成功后直接返回Json.
无法针对用户, 只能全部授权给第三方应用.

更新Token

https://third.com/oauth/token? //应用访问第三方网址
  grant_type=refresh_token& //表示更新Token
  client_id=CLIENT_ID& //表明应用身份
  client_secret=CLIENT_SECRET& //证明应用身份
  refresh_token=REFRESH_TOKEN //更新Token

第三方服务器成功后直接返回Json.

米家OAuth

首先是前面折腾网关时接触到的的米家 OAuth 登录.

这几天没事又看了一遍米家文档(顺便熟悉OAuth)(2/21)
这里简述一下米家和第三方服务器鉴权和通信流程吧:
米家使用 OAuth 2.0 实现鉴权. 第三方服务商需要在米家平台填写以下参数:

  • 登录页面(让用户输入账号密码的页面)
  • Client ID/Client Secret
  • Access Token URL/Refresh URL(获取Token/更新Token地址)
  • 设备指令接收URL(鉴权完成后发送控制数据的地址)

遵循以下流程(仅米家的流程):

  1. 用户(用户代理)访问 登录页面 ,带上 client_id(表明第三方身份)/redirect_uri(米家服务器).(GET方式)
  2. 登录页面 进行验证, 通过后访问 redirect_uri(米家服务器) 里的地址, 并在 redirect_uri 后加上 code(授权码).(GET方式)
  3. redirect_uri(米家服务器) 可以调起后端程序, 后端程序带上 code(获得的授权码)/redirect_uri/client_secret(证明身份|重点) 访问 Access Token URL(重点).
  4. Access Token URL(第三方服务器) 的收到code(授权码)后访问 redirect_uri(米家服务器) 并带上 access_token/token_type/expires_in
  5. 米家服务器通过接收到 Token, 随后即可带上 access_token 访问 设备指令接收URL.(接下来就是MIOT自行规定的协议了)

可以通过上述流程看出我们要实现OAuth的重点是获得 Access Token URL 和 client_secret, 然而这两个参数都是在米家服务器上的, 所以达咩.

CAS流程

发现CAS的流程和OAuth的授权码流程很像, 都是携带GET参数访问资源服务器.
因为不大可能会遇到, 我就不详细讲了.

  1. 访问 pan.a.com(资源服务器), 服务器检测登录状态后重定向至 cas.b.com(CAS服务器)(注意是不同域名的, 重定向时携带redirect_uri)
  2. cas.b.com(CAS服务器) 要求登录, 验证后创建TGT(Ticket Granted Ticket, 存储在CAS服务器, 类似于SESSION), 设置Cookie: TGC(Ticket Granted Cookie, 由TGT生成, 再次访问CAS时可实现直接登录), 再次重定向回redirect_uri并携带GET参数ST(也是由TGT生成 ,类似于OAuth的code授权码, 一次性).
  3. pan.a.com(redirect_uri)拿着ST再向CAS服务器验证, 通过后即可发放自己的SESSION和Cookie, 实现登录.
最后修改:2021 年 03 月 02 日 08 : 15 PM