为什么需要授权码?

在 OAuth 2.0 的体系里面有 4 种角色,按照官方的称呼它们分别是资源拥有者、客户端、授权服务和受保护资源。不过,这里的客户端,我更愿意称其为第三方软件,而且在咱们这个课程中,都是以第三方软件在举例子。所以,在后续的讲解中我统一把它称为第三方软件。
资源拥有者 -> 小明,第三方软件 -> 小兔软件,授权服务 -> 京东商家开放平台的授权服务,受保护资源 -> 小明店铺在京东上面的订单。

突然看到这个序列图增加了这么多步骤的时候,你是不是有些紧张?那如果我告诉你再细分的话步骤还要更多,你是不是就更困惑了?不过,别紧张,这没啥关系。一方面,咱们这一讲的重点就是跟授权码相关的流程,你只需关注这里的重点步骤,也就是两次重定向相关的步骤就够了。在下一讲中,我再教你如何将这些步骤进一步拆解。另一方面,我接下来还会用另一种视角来帮助你分析这个流程。
我们继续来看这张序列图。从图中看到,在第 4 步授权服务生成了授权码 code,按照一开始我们提出来的问题,如果不要授权码,这一步实际上就可以直接返回访问令牌 access_token 了。
按着这个没有授权码的思路继续想,如果这里直接返回访问令牌,那我们肯定不能使用重定向的方式。**因为这样会把安全保密性要求极高的访问令牌暴露在浏览器上,从而将会面临访问令牌失窃的安全风险。**显然,这是不能被允许的。也就是说,如果没有授权码的话,我们就只能把访问令牌发送给第三方软件小兔的后端服务。按照这样的逻辑,上面的流程图就会变成下面这样:

到这里,看起来天衣无缝。小明访问小兔软件,小兔软件说要打单你得给我授权,不然京东不干,然后小兔软件就引导小明跳转到了京东的授权服务。到授权服务之后,京东商家开放平台验证了小兔的合法性以及小明的登录状态后,生成了授权页面。紧接着,小明赶紧点击同意授权,这时候,京东商家开放平台知道可以把小明的订单数据给小兔软件。

于是,京东商家开放平台没含糊,赶紧生成访问令牌 access_token,并且通过后端服务的方式返回给了小兔软件。这时候,小兔软件就能正常工作了。

这样,问题就来了,什么问题呢?当小明被浏览器重定向到授权服务上之后,小明跟小兔软件之间的 “连接” 就断了,相当于此时此刻小明跟授权服务建立了“连接”后,将一直“停留在授权服务的页面上”。你会看到图 2 中问号处的时序上,小明再也没有重新“连接”到小兔软件。

但是,这个时候小兔软件已经拿到了小明授权之后的访问令牌,也使用访问令牌获取到了小明店铺里的订单数据。这时,考虑到“小明的感受”,小兔软件应该要通知到小明,但是如何做呢?现在“连接断了”,这事儿恐怕就没那么容易了。

OK,为了让小兔软件能很容易地通知到小明,还必须让小明跟小兔软件重新建立起 “连接”。这就是我们看到的第二次重定向,小明授权之后,又重新重定向回到了小兔软件的地址上,这样小明就跟小兔软件有了新的 “连接”。

为了重新建立起这样的一次连接,我们又不能让访问令牌暴露出去,就有了这样一个临时的、间接的凭证:授权码。因为小兔软件最终要拿到的是安全保密性要求极高的访问令牌,并不是授权码,而授权码是可以暴露在浏览器上面的。这样有了授权码的参与,访问令牌可以在后端服务之间传输,同时呢还可以重新建立小明与小兔软件之间的“连接”。这样通过一个授权码,既“照顾”到了小明的体验,又“照顾”了通信的安全。

授权码许可类型的通信过程

图 1 的通信过程中标识出来的步骤就有 9 个,一步步地去分析看似会很复杂,所以我会用另一个维度来分析以帮助你理解,也就是从直接通信和间接通信的维度来分析。这里所谓的间接通信就是指获取授权码的交互,而直接通信就是指通过授权码换取访问令牌的交互。
接下来,我们就一起分析下吧,看看哪些是间接通信,哪些又是直接通信。

间接通信

我们先分析下为什么是“间接”。

我们把图 1 中获取授权码 code 的流程 “放大”,并换个角度来看一看,也就是将浏览器这个代理放到第三方软件小兔和授权服务中间。于是,我们来到了下面这张图:
这个过程,仿佛有这样的一段对话。
小明:“你好,小兔软件,我要访问你了。”
小兔软件:“好的,我把你引到授权服务那里,我需要授权服务给我一个授权码。”
授权服务:“小兔软件,我把授权码发给浏览器了。”
小兔软件:“好的,我从浏览器拿到了授权码。”

不知道你注意到没有,第三方软件小兔和授权服务之间,并没有发生直接的通信,而是**通过浏览器这个“中间人” 来 “搭线”的。**因此,我们说这是一个间接通信的方式。

直接通信

那我们再分析下,授权码换取访问令牌的交互,为什么是“直接”的。我们再把图 1 中获取访问令牌的流程“放大”,就得到了下面的图示:

相比获取授权码过程的间接通信,获取访问令牌的直接通信就比较容易理解了,就是第三方软件小兔获取到授权码 code 值后,向授权服务发起获取访问令牌 access_token 的通信请求。这个请求是第三方软件服务器跟授权服务的服务器之间的通信,都是在后端服务器之间的请求和响应,因此也叫作后端通信。

两个 “一伙”

了解了上面的通信方式之后,不知道你有没有意识到,OAuth 2.0 中的 4 个角色是 “两两站队” 的:资源拥有者和第三方软件“站在一起”,因为第三方软件要代表资源拥有者去访问受保护资源;授权服务和受保护资源“站在一起”,因为授权服务负责颁发访问令牌,受保护资源负责接收并验证访问令牌。


讲到这里的时候,你会发现在这一讲,介绍授权码流程的时候我都是以浏览器参与的场景来讲的,那么浏览器一定要参与到这个流程中吗?

其实,授权码许可流程,不一定要有浏览器的参与。接下来,我们就继续分析下其中的逻辑。

一定要有浏览器吗?

OAuth 2.0 发展之初,开放生态环境相对单薄,以浏览器为代理的 Web 应用居多,授权码许可类型 “理所当然” 地被应用到了通过浏览器才能访问的 Web 应用中。
但实际上,OAuth 2.0 是一个授权理念,或者说是一种授权思维。
它的授权码模式的思维可以移植到很多场景中,比如微信小程序。

在开发微信小程序应用时,我们通过授权码模式获取用户登录信息,官方文档的地址示例中给出的 grant_type=authorization_code ,就没有用到浏览器。

根据微信官方文档描述,开发者获取用户登录态信息的过程正是一个授权码的许可流程:

  1. 首先,开发者通过 wx.login(Object object) 方法获取到登录凭证 code 值,这一步的流程是在小程序内部通过调用微信提供的 SDK 实现;
  2. 然后,再通过该 code 值换取用户的 session_key 等信息,也就是官方文档的 auth.code2Session 方法,同时该方法也是被强烈建议通过开发者的后端服务来调用的。

你可以看到,这个过程并没有使用到浏览器,但确实按照授权码许可的思想走了一个完整的授权码许可流程。也就是说,先通过小程序前端获取到 code 值,再通过小程序的后端服务使用 code 值换取 session_key 等信息,只不过是访问令牌 access_token 的值被换成了 session_key。

总结

这节课又接近尾声了,我再带你回顾下重点内容。今天,我从为什么需要授权码这个问题开始讲起,并通过授权码把授权码许可流程整体的通信过程串了一遍,提到了授权码这种方式解决的问题,也提到了授权码流程的通信方式。总结来说,我需要你记住以下两点。

  1. 授权码许可流程有两种通信方式。一种是前端通信,因为它通过浏览器促成了授权码的交互流程,比如京东商家开放平台的授权服务生成授权码发送到浏览器,第三方软件小兔从浏览器获取授权码。**正因为获取授权码的时候小兔软件和授权服务并没有发生直接的联系,也叫做间接通信。**另外一种是后端通信,在小兔软件获取到授权码之后,在后端服务直接发起换取访问令牌的请求,也叫做直接通信。
  2. 在 OAuth 2.0 中,访问令牌被要求有极高的安全保密性,因此我们不能让它暴露在浏览器上面,只能通过第三方软件(比如小兔)的后端服务来获取和使用,以最大限度地保障访问令牌的安全性。正因为访问令牌的这种安全要求特性,当需要前端通信,比如浏览器上面的流转的时候,OAuth 2.0 才又提供了一个临时的凭证:授权码。**通过授权码的方式,可以让用户小明在授权服务上给小兔授权之后,还能重新回到小兔的操作页面上。**这样,在保障安全性的情况下,提升了小明在小兔上的体验。

从授权码许可流程中就可以看出来,它完美地将 OAuth 2.0 的 4 个角色组织了起来,并保证了它们之间的顺畅通信。它提出的这种结构和思想都可以被迁移到其他环境或者协议上,比如在微信小程序中使用授权码许可。

OAuth 2.0 基础(2)相关推荐

  1. OAuth2.0 基础概述

    web:http://oauth.net/2/ rfc:http://tools.ietf.org/html/rfc6749 doc:http://oauth.net/documentation/ c ...

  2. oauth2_带有Spring Security的OAuth 2.0快速指南

    oauth2 "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验 ...

  3. 别再搞错!OAuth 2.0只是授权协议,OIDC才是认证授权协议

    上一文我们对Keycloak保护Spring Boot应用进行了实操.让大家见识到了Keycloak的强大.为了掌握Keycloak就必须对OpenID Connect(OIDC)协议进行了解. OI ...

  4. 可能是第二好的 Spring OAuth 2.0 文章,艿艿端午在家写了 3 天~

    " 本文在提供完整代码示例,可见 https://github.com/YunaiV/SpringBoot-Labs 的 lab-68-spring-security-oauth 目录. 原 ...

  5. OAuth 2.0 协议学习笔记

    协议官网 在传统的客户端-服务器身份验证模型中,客户端通过使用资源所有者的凭据向服务器进行身份验证来请求服务器上的访问受限资源(受保护资源). 为了向第三方应用程序提供对受限资源的访问,资源所有者与第 ...

  6. 带有Spring Security的OAuth 2.0快速指南

    "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证. 在构建W ...

  7. OAuth 2.0 - Authorization Code授权方式详解

    I:OAuth 2.0 开发前期准备 天上不会自然掉馅饼让你轻松地去访问到人家资源服务器里面的用户数据资源,所以你需要做的前期开发准备工作就是把AppKey, AppSecret取到手 新浪获取传送门 ...

  8. 一个功能完备的.NET开源OpenID Connect/OAuth 2.0框架——IdentityServer3

    今天推荐的是我一直以来都在关注的一个开源的OpenID Connect/OAuth 2.0服务框架--IdentityServer3.其支持完整的OpenID Connect/OAuth 2.0标准, ...

  9. 0基础学python要多久-怎么自学python,大概要多久?

    学编程语言有个小秘诀,直接上项目就是干,做完后你就是pythoner了. 不要怕没有基础,边做边查边学,进步很快的. 因人而异,一周或者一个月就能搞定.当然需要足够的投入. 以前我也觉得收集资料.啃语 ...

最新文章

  1. Go 学习笔记(49)— Go 标准库之 io/ioutil(读写文件、获取目录下的文件和子目录、创建临时目录和文件)
  2. New Year Tree(dfs序+线段树+二进制)
  3. android loadlibrary 更改libPath 路径,指定路径加载.so
  4. 富文本编辑器宽度自适应及取消自动保存功能
  5. 如何解决UltraCompare中中文显示乱码的问题
  6. 测试必备:if条件测试( if-else语句、if-elif-else语句、多个elif代码块、省略else代码块、测试多个条件)
  7. 点击部分刷新html ajax,一文全解web前端精简知识点
  8. DBShop电子商务系统
  9. scrum回顾_[PM]敏捷开发之Scrum总结
  10. rocketmq怎么保证数据不会重复_阿里架构师亲授:Kafka和RocketMQ的消息复制实现的差异点在哪?...
  11. SQL Server高级查询之常见数据库对象(数据库事务)第五章节
  12. eval函数python_Python eval()函数
  13. 白话用consul作为注册中心搭建微服务
  14. Tableau 2021安装教程
  15. 完美显示html的版权符号
  16. wps一直显示正在备份怎么办_wps一直显示正在保存
  17. 2021年,Cat.1仍将是物联网的中流砥柱
  18. MQL5 代码自动生成文档
  19. java设计模式 课后习题参考答案 第 2 章 面向对象设计原则 清华出版社 刘伟
  20. 摄像头模组 OTP(One Time Programmable) P1

热门文章

  1. 最近进行的一次技术选型(工作流引擎)及相关知识介绍
  2. 华为TE10一体化视频会议终端
  3. 学习-Java继承和多态之子类继承性
  4. 零基础学黑客攻防 :实现简单的QQ/邮件黑客攻击,注册表/系统安全防护,黑客零基础入门最佳教程
  5. 教程 | 用Python识别图片验证码中的文字
  6. Linux自动化部署Web服务
  7. 浏览器查看请求与响应报文
  8. YLAN_TRANSLATE ABAP程序批量翻译工具
  9. jpa整合querydsl实现简单查询以及左联查询
  10. 测试开发工程师成长日记018 - 测试面试必备题记录(持续更新)