一篇文章看懂 OAuth2
一、概述
OAuth 是一份关于允许用户授权第三方应用访问其存储在其他网站上资源,而无需将用户名密码提供给第三方网站的开放标准。OAuth2 是 OAuth 的最新版本,同时也是被广泛应用的一个版本。
OAuth2 标准定义了一个 “用户授权 -> 数据获取” 的流程,理解了这个流程,也就理解了 OAuth2 的整体思路。
二、角色
流程即不同角色之间的交互,在进入具体的流程描述之前,我们需要了解流程中涉及的角色有哪些。OAuth2 中涉及的角色包括:
资源所有者(Resource Owner)
资源所有者就是用户,为了便于理解,以下简称为用户。
资源服务器(Resource Server)
资源服务器就是存储用户资源的服务器。
客户端(Client)
客户端也被称为第三方应用,即需要得到用户授权,让它可以访问用户资源的应用。在 Web 环境中,客户端由 “服务器” 和 “运行于浏览器中的网页” 组成,而在手机环境中,客户端由 “服务器” 和 “App” 组成。
授权服务器(Authorization Server)
授权服务器即为客户端颁发访问令牌(Access Token)的服务器。访问令牌是客户端访问资源服务器中存放的用户资源所需要出示的凭据,访问令牌一般会有资源访问权限(如,读、写、读写)、访问范围(如,所有数据、部分数据)、访问时间(如,一天、一小时)的限制。只有得到用户的授权,授权服务器才会为客户端颁发访问令牌。
三、整体流程
基于 OAuth2 的数据获取流程如上图所示,整个流程可以归纳为以下三个部分:
- 获取授权凭据。客户端向用户发起授权申请,用户自行决定是否允许客户端访问自己的资源,若用户允许客户端访问,则客户端会获得一个授权凭据。授权凭据是一个代表用户授权访问其资源的证明,在 OAuth 流程中,授权凭据主要用来交换访问令牌。
- 获取访问令牌。客户端携带上一步获取到的授权凭据向授权服务器发起请求,授权服务器验证客户端的身份和授权凭据后,向客户端颁发访问令牌。通常情况下,访问令牌的过期时间比较短,为了避免频繁的向用户申请授权,授权服务器在下发访问令牌的同时,还会下发一个“更新令牌”,更新令牌是用来给客户端刷新访问令牌用的。
- 获取用户资源。客户端携带访问令牌请求资源服务器,获取特定用户的资源,进行其他的业务操作。
四、不同类型的授权凭据
在 OAuth2 中,授权凭据存在 4 种不同的类型,在整体流程的「获取授权凭据」部分,不同类型的授权凭据让流程中的角色产生不同的交互。
授权码
授权码顾名思义即用户授权的凭据是一个“授权码”。大部分基于 OAuth2 的用户数据获取流程都使用授权码形式的授权凭据。授权码类型的流程如下:
- 用户访问客户端后,客户端引导用户访问授权服务器,通常情况下,在用户触发某些操作后,客户端会跳转授权服务器,跳转链接一般会携带客户端重定向链接,便于授权服务器重定向回客户端。
- 授权服务器向用户申请授权。
- 用户允许授权后,授权服务器引导用户携带授权码跳转到客户端。一般情况下,授权服务器会使用重定向链接跳转回客户端。
- 客户端服务器若检测到重定向链接中拼接的授权码,则使用授权码向授权服务器发起请求获取访问令牌。
隐式授权
隐式授权即不产生授权码的授权码模式,在隐式模式中,整个流程不存在授权码,用户在授权服务器授权通过后,授权服务器会直接生成访问令牌继续执行后面的操作,隐式模式适用于存在 “运行于浏览器中的网页” 的客户端,它的流程如下:
- 用户访问客户端后,客户端引导用户跳转授权服务器,跳转链接包含重定向回客户端的链接。
- 授权服务器向用户申请授权。
- 用户允许授权后,授权服务器使用重定向链接跳转回客户端,并在重定向链接后以 hash 形式(类似于 #foo,浏览器中的网页链接的 hash 不会随请求发送给服务器)拼接访问令牌。
- 客户端服务器在重定向链接中返回获取保存在 hash 中访问令牌的脚本,浏览器执行脚本后即可获取访问令牌。
密码凭据
密码凭据即客户端主动向用户申请访问资源所需的账号密码,然后使用账号密码向授权服务器发起请求,获取访问令牌。密码凭据适用于用户高度相信客户端的情况。
客户端凭据
在客户端凭据类型下,客户端即用户。在这种类型下,客户端直接向授权服务器发起请求获取访问令牌,不需要其他额外的证明。
五、使用
以下使用 Node.js 演示授权码类型下获取 GitHub 的 OAuth2 授权,涉及的库包括:
- koa
- axios
- pug
注册 GitHub OAuth 应用
OAuth2 是一个获取用户存储在其他网站上数据的标准,我们想要获取用户数据,就得先到用户数据所在的网站进行注册应用,GitHub 的 OAuth2 应用注册地址是 https://github.com/settings/applications/new,具体界面如下图所示。
上图中,Homepage URL 指的是你应用的地址,由于我们是本地测试应用,所以填写测试地址即可。Authorization callback URL 一项中填写的是用户授权后,授权服务器的回调地址。
点击 Register application 注册成功后,GitHub 会生成客户端 ID(Client ID)和客户端密钥(Client Secret ),这两个数据在后续的请求需要用到,需要保存到服务器应用
用户点击链接跳转到 GitHub 进行授权
对于浏览器应用而言,只需要在浏览器界面展示一个跳转 GitHub 的授权链接,用户点击了即可去 GitHub 授权。
// view/index.pug // html 设置授权链接,并拼接 client_id doctype html html head body a(href='https://github.com/login/oauth/authorize?client_id=' + clientId) 获取授权
授权回调处理
服务端定义 GitHub 授权回调路由,并使用回调参数交换访问令牌,再使用访问令牌获取用户信息。
// router.js router.get('/redirect', async (ctx) => { const code = ctx.query.code // Code 为 GitHub 拼接在重定向链接后的参数 if (!code) { ctx.throw(400, '回调 URL 无 code 字段') return } // GitHub OAuth 要求参数 const param = { client_id: config.clientId, client_secret: config.clientSecret, code, } // GitHub 交换访问令牌默认返回字符串,通过设置 accept 来控制结果返回 json 字符串 const opt = { headers: { accept: 'application/json', }, } // 使用 code 交换访问令牌 const { data } = await axios.post('https://github.com/login/oauth/access_token', param, opt) const accessToken = data.access_token if (!accessToken) { ctx.throw(500, '交换访问令牌失败') return } const { data: user } = await axios.get('https://api.github.com/user', { headers: { Authorization: `token ${accessToken}`, }, }) if (!user) { ctx.throw(500, '用户数据获取失败') return } ctx.body = user })
查看完整代码请前往 GitHub 搜索用户 yo-squirrel
觉得写得不错可以关注下微信公众号「松鼠专栏」
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
基于函数计算的 BFF 架构
什么是 BFF BFF 全称是 Backends For Frontends (服务于前端的后端),起源于 2015 年 Sam Newman 一篇博客文章《Pattern: Backends For Frontends —— Single-purpose Edge Services for UIs and external parties》。 微服务和前后端分离的流行,在后端服务边界上通常会有一个 API 层,向下调系统内的多个微服务,经过聚合、适配和裁剪等一些列的处理后,向上为前端提供 HTTP 协议的 API。 然后随着移动端的兴起,出现了 H5、iOS 和 Android 等多端并存的开发场景,由于移动端的屏幕尺寸比较小,所以显示的信息和传统 Web 端会有较大的区别,而且移动端对于访问连接数和数据量也有更高的要求。此时通用 API 层的开发就会碰到一些困境,比如需要为不同的端提供不同的 API。而这些 API 的设计与不同端上的展示逻辑相关性较强,所以不太适合由后端团队或者 API 团队来负责。因为这些 API 的维护人员会夹在前后端之间去做协调和取舍,非常的心累。 Sam ...
- 下一篇
应用交付厂商F5助力保险公司云战略转型
在疫情爆发后,宏康人寿仅用一周的时间就完成了新产品——弘康安康保:新冠风险保障金的上架。这样的速度缘于弘康人过硬的业务与技术能力,也离不开持续多年的科技投入与IT云战略的推进。多年来,在应用交付厂商F5、阿里云等众多IT合作伙伴的协助下,弘康人寿已经逐步实现了从传统IT架构跨向云的转变,进而驱动业务的高速成长。 受到疫情的影响,保障产品上线后,尽管保单量的激增在弘康人寿的预判范围内,但面对高于平常数倍的业务高峰依然对保单的装载和数据加工带来了压力。在这么紧急的项目中,应用交付厂商F5很好地保障了网络入口的通畅,流量的均匀分配使得后端的销售、核保、短信平台等应用系统有充足的时间处理和加工数据。 应用交付厂商F5助力保险公司云战略转型 2014年,弘康人寿便在行业内率先应用阿里金融云。但向云端的迁移带来了很多挑战:之前数据中心用的交付策略、可靠性策略、防护策略配置等不能完全适用云环境。特别是往后如果应用不同厂商的云服务时,怎么能保持策略的一致性,串联起几朵云之间的资源优势是需要提前考量的一点。除此以外,弘康人寿还希望收集更多用户访问数据,通过大数据分析为产品研发和互联网营销提供支持。 实...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS8编译安装MySQL8.0.19
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7