首页 文章详情

OAuth2.0从入门到出道

码农沉思录 | 199 2020-10-26 00:12 0 0 0
UniSMS (合一短信)

什么是OAuth2

我们都知道,很多网站登录的时候,可以通过微信、QQ、微博等APP扫码扫码认证登录,其实这就是OAuth2的应用。
但是这里我想说明的是oauth2是一种授权许可。它的核心本质是用于授权,获取用户的资源信息,而不是用于登录。登录是它的附加产物。这个细节我们一定要理解清楚,以便于后续理解整个OAuth2时,不会让自己无法理清它的核心逻辑。

OAuth2的几种不同的“角色”

在这里让我们用“掘金”这个网站的登录来举例子吧!
  1. 资源拥有者:掘金的用户
  2. 第三方软件:掘金(有些文章叫做客户端)
  3. 授权服务:微信开放平台的授权服务
  4. 受保护的资源:微信头像、微信其他信息

OAuth2的几种类型

  1. 授权码凭据许可
  2. 资源拥有者凭据许可(账号密码类型)
  3. 客户端凭据许可
  4. 隐式许可(简单类型)

授权码凭据许可

官方流程

OAuth2官方流程.png
不知道你们是什么感受,反正我看官方的图,我觉得我理解能力有限,不知道整个流程到底是咋样的。

掘金登录流程

我们还是以掘金网站为案例,以下是登录掘金的全流程:
  1. 用户打开掘金
  2. 用户点击登录(微信登录)
  3. 界面跳转到微信扫码页面
  4. 用户扫码登录
  5. 用户授权并同意
  6. 登录成功,页面跳转回掘金

掘金登录详细流程

以上是我们用户能感知到的全流程,但是整个流程的服务交互,我们仍然不知道。下面我再以服务交互的角度,更详细描述下整个登录流程:
  1. 用户打开浏览器,打开掘金
  2. 用户点击登录
  3. 页面跳转到微信扫码页面
  4. 微信授权服务校验掘金的请求信息
  5. 用户用微信扫码
  6. 用户用微信授权并同意
  7. 微信授权服务校验用户信息
  8. 页面跳转到掘金前端页面并附带上授权码
  9. 掘金前端用授权码请求掘金后端
  10. 掘金后端调用微信的OpenApi请求访问令牌
  11. 微信授权服务校验授权码及掘金的请求信息,并响应访问令牌
  12. 掘金后端拿到访问令牌,并通过访问令牌获取用户信息(用户唯一ID、微信头像,用户名等)
  13. 掘金后端记录用户登录
  14. 掘金后端响应前端用户登录成功
  15. 掘金前端给用户展示登录成功页面
通过以上来看,整个流程真的挺复杂的,步骤繁多。所以我用时序图给大家画出来这一切的交互

掘金OAuth2登录流程.png

我们需要重点关注的几个步骤

  • 第三点与第四点(跳转到微信扫码登录页)
    当我们从掘金跳转到微信扫码页面的时候,我们可以观察下微信扫码页面的URL
    https://open.weixin.qq.com/connect/qrconnect?appid=wx1f78f78832fc2c16&redirect_uri=https%3A%2F%2Fjuejin.im%2Fpassport%2Fauth%2Flogin_success&response_type=code&scope=snsapi_login&state=0d26ae7d3gASoVCgoVPZIDU5OTlkODY2ZDg1MTA1YmJkYjhjOTY4NzI4Y2VkMzYzoU6-aHR0cHM6Ly9qdWVqaW4uaW0vb2F1dGgtcmVzdWx0oVYBoUkAoUQAoUHRCjChTdEKMKFIqWp1ZWppbi5pbaFSBKJQTNEDQaZBQ1RJT06goUyyaHR0cHM6Ly9qdWVqaW4uaW0voVTZIDJjNzMzMWI5YzdkMzk5MzljYjYyYjdiODllOTJlNDZioVcAoUYAolNBAKFVww%253D%253D#wechat_redirect
URL中有三个关键参数
  • appid:appId,第三方的唯一标识
  • redirect_uri:授权成功后的跳转URL
  • scope:权限范围
关于appId,这里稍微补充一下。当掘金需要利用微信做第三方授权登录时,掘金需要去微信的开放平台上面“注册”。这个“注册”操作,其实就是申请appId、appSecret、填写授权成功后的跳转URL、以及掘金的权限范围。
当我们跳转到微信扫码登录页的时候,会把appId、授权成功后的跳转URL、权限范围作为参数,这时微信的授权服务其实会根据appId进行一系列的校验:
  • appId是否正确(你不能随便瞎传一个appId,否则微信怎么知道是否是合法的第三方呢?)
  • 根据appId校验授权成功后的跳转URL是否正确(如果跳转的URL不是注册时填写的URL,是不被允许的)
  • 根据appId校验第三方的权限范围是否正确(第三方本次授权的权限范围不能超过它申请时的范围。比如申请时只需要查询用户信息,但是本次授权却需要查询用户好友列表,这肯定是不被微信允许的)
当验证信息通过后,微信授权页面才会打开,展示用户扫码的页面。
  • 第七点(校验用户授权信息)
    当用户用微信授权并同意的时,这时用户会提交授权同意信息给微信授权服务。这时,微信授权服务主要做三个任务:
    • 验证权限范围:第三方软件可能需要用户个人信息、用户好友列表、用户所在地等权限信息,但是作为用户为了保护自己的隐私,不一定会把全部的信息给到第三方,用户可以自由选择哪些允许授权。
    • 生成授权码:当用户同意授权后,微信授权服务会为本次授权生成授权码。
    • 重定向至第三方URL:微信授权服务授权码成功后,需要告知第三方软件,它要通过跳转到第三方的URL上。
  • 第八点(授权码)
    授权码是一个非常关键的信息,它用于后续与appSecret配合,获取访问令牌。关于授权码,我们要知道的是:
    这里授权码生命周期设计的如此短,而且它是一次性的,主要是为了安全。因为授权码是微信通过重定向跳转到第三方URL上的,所以授权码是直接暴露在外的。
    • 授权码是一次性的,用了一次之后,微信会把它作废,后续想要使用,必须使用新的授权码。
    • 授权码是有时间限制的,而且这个时间是非常短的,官方推荐是10分钟以内,而大部分授权平台授权码的有效时间一般是3~5分钟。
  • 第十点(访问令牌)
    掘金想要访问到用户的资源,最终还是要通过访问令牌去请求用户的资源。授权码其实只是一个临时的通行证。获取访问令牌有三个关键参数:
    微信根据上述三个参数,校验第三方是否存在,appSecret是否正确,授权码是否正确来生成访问令牌。
    至于访问令牌的种类,不同的软件授权服务有不同的规则,它可以是一串UUID,也可以是JWT,我们日常使用的token都适合的。只不过大家要注意的是,OAuth2和JWT其实并没有绝对依赖的关系,不要一开始就把二者混为一谈,否则后续很容易让自己云里雾里。
    当掘金拿到访问令牌后,就可以访问用户资源接口,获取用户信息了。
    其实很多人不理解,为什么要弄一个授权码还弄一个访问令牌呢?直接一步到位不就好了吗?
    我们仔细看看时序图,授权码是微信通过浏览器的URL重定向告诉掘金的,所以基本上没啥安全性可言,大家都能知道它;
    而访问令牌则是掘金的后端服务器直接与微信授权服务通信,获取到的,因此它的安全性是比较好的。
    另外,有些软件授权服务不仅仅会返回访问令牌(accessToken),还会返回一个刷新令牌(refreshToken)。刷新令牌的作用其实和授权码很相似,就是通过刷新令牌获取访问令牌,而且访问令牌也是一次性的,也有有效期,只不过它的有效期会相对比较久,有些软件的刷新令牌有效期是一周。
    为什么有这个刷新令牌呢?因为访问令牌是有有效期的。假设没有刷新令牌,当访问令牌过期后,如果第三方软件还要继续获取用户资源信息,那么只有一个办法了:告诉用户访问令牌过期,让用户重新走一遍访问令牌申请流程。毫无疑问,这个用户体验是非常差的。而如果有刷新令牌,那么第三方软件可以再访问令牌过期前,在后端静默的申请一个新的访问令牌,而整个流程是用户无感知的。

    大厂获取accessToken的时序图

    微信授权接入文档
    • 微信
    • appId:用户的唯一标识,微信授权服务需要校验第三方是否存在
    • appSecret:还记得上述我们说过,掘金需要去微信开放平台注册时的申请的appSecret吗?就是在这里用上了。
    • 授权码:第八点生成的授权码
微信获取accessToken时序图.png
  • 支付宝
支付宝授权接入文档
支付宝获取accessToken时序图.png

资源拥有者凭据许可(账号密码类型)

关于资源拥有者凭据许可,我们可以换个方式想象一下。假设,微信把掘金收购了,也就是掘金变成了微信的,那么微信账号密码直接告诉给掘金也没关系,反正大家都是一家人,也不存在什么账号密码泄露的问题,用同一套登录服务就行了。
那么用户就能直接用微信的账号密码获取访问令牌,后续掘金获取用户资源直接利用访问令牌就可以了。

客户端凭据许可

客户端凭据许可这个类型的应用场景,其实主要是“资源拥有者被塞进了第三方软件中” 或者 “第三方软件就是资源拥有者”。它主要是通过appId与appSecret获取访问令牌直接访问用户资源。
大家可以想象一下“云存储服务器”。比如“七牛云存储”、“阿里云OSS”,我们可以用我们自己编写的软件,访问我们的云盘。而我们作为资源拥有者,与我们自己的软件合二为一。而且我们的软件与“七牛云存储”、“阿里云OSS”是直接通过后端交互访问的,所以安全性会比较好,可以直接通过appId与appSecret获取访问令牌。

隐式许可(简单类型)

这种类型其实应用的非常少,主要是用于第三方软件只有前端,没有后端的情况。因为只有前端,所以第三方软件直接嵌入浏览器中,通过浏览器与授权服务交互。这种情况,基本上就没有所谓的安全性可言了,因此也不需要appSecret了,前端直接通过appId就可以获取到accessToken。

点个在看支持我吧,转发就更好了
good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter