关于 OAuth 你又了解哪些?
作者罗锦华,API7.ai 技术专家/技术工程师,开源项目 pgcat,lua-resty-ffi,lua-resty-inspect 的作者。
OAuth 的背景
OAuth,O 是 Open,Auth 是授权,也就是开放授权的意思。OAuth 始于 2006 年,其设计初衷正是委托授权,就是让最终用户也就是资源拥有者,将他们在受保护资源服务器上的部分权限(例如查询当天订单)委托给第三方应用,使得第三方应用能够代表最终用户执行操作(查询当天订单)。
OAuth 1.0 协议于 2010 年 4 月作为 RFC 5849 发布,这是一份信息性的评论请求。OAuth 2.0 框架的发布考虑了从更广泛的 IETF 社区收集的其他用例和可扩展性要求。尽管基于 OAuth 1.0 部署体验构建,OAuth 2.0 并不向后兼容 OAuth 1.0。OAuth 2.0 于 2012 年 10 月作为 RFC 6749 发布,承载令牌使用作为 RFC 6750 发布。
在 OAuth 协议中,通过为每个第三方软件和每个用户的组合分别生成对受保护资源具有受限的访问权限的凭据,也就是访问令牌,来代替之前的用户名和密码。而生成访问令牌之前的登录操作,又是在用户跟平台之间进行的,第三方软件根本无从得知用户的任何信息。
这样第三方软件的逻辑处理就大大简化了,它今后的动作就变成了请求访问令牌、使用访问令牌、访问受保护资源,同时在第三方软件调用大量 API 的时候,不再传输用户名和密码,从而减少了网络安全的攻击面。
说白了就是集中授权。
值得注意的是,OAuth 并非身份验证,这里的 Auth 是 Authorization,OAuth 是发生在用户做了身份验证后的事情,系统授权用户能做什么操作。互联网中所有的受保护资源,几乎都是以 Web API 的形式来提供访问的。不同的用户能做的事情不同,例如一个 GitHub 项目,有些用户只有读取和提交 PR(pull request)的权限,而管理员用户则能合并 PR。将用户权限在 API 层面细分,是 OAuth 要做的事情。
OAuth的授权流程
角色
在 OAuth 2.0 的体系里面有四种角色:
- 第三方应用:一般分为前端浏览器、APP 和后端应用服务器。
- 资源拥有者:使用第三方应用的用户,并在授权服务器上有账号。
- 授权服务:提供授权的开发平台,例如微博、GitHub、微信。
- 受保护资源:用户的各类信息,例如用户名、头像、昵称、邮箱等信息。
流程
步骤A:第三方应用向用户(其实是通过授权服务器)申请授权码
步骤B:授权服务器返回授权码给第三方应用
步骤C:第三方应用将授权码发给资源服务器,申请访问口令
步骤D:授权服务器返回访问口令给第三方应用
步骤E:第三方应用使用访问口令向资源服务器请求用户信息
步骤F:资源服务器返回用户信息,第三方应用提供业务逻辑给用户
授权码和访问口令
获取访问口令的方式在标准里有四种,这里只谈论授权码方式,这也是最常见最安全的方式:
步骤 A:第三方应用让用户选择授权方式,例如 GitHub,然后携带client_id
和redirect_uri
等参数将用户重定向到授权服务器
请求示例:
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.13 Host: server.example.com
步骤 B:用户登录和授权 步骤 C:授权服务器根据redirect_uri
将用户重定向回到第三方应用的后端,提供授权码
响应示例:
1 HTTP/1.1 302 Found
2 Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
3 &state=xyz
步骤 D:第三方应用的后端访问授权服务器,用授权码去换访问口令 请求示例:
1 POST /token HTTP/1.1
2 Host: server.example.com
3 Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
4 Content-Type: application/x-www-form-urlencoded
5
6 grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
7 &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
步骤 E:授权服务器返回访问口令,第三方应用的后端渲染功能页面(对应步骤C)给浏览器,为用户提供功能 授权服务器的响应示例:
HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8Cache-Control: no-storePragma: no-cache{"access_token":"2YotnFZFEjr1zCsicMWpAA","token_type":"example","expires_in":3600,"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA","example_parameter":"example_value"}
实际场景示例
小明想通过小兔软件打印他在京东上的订单。
资源拥有者 -> 小明
第三方软件 -> 小兔软件
授权服务 -> 京东商家开放平台的授权服务
受保护资源 -> 小明店铺在京东上面的订单
为什么授权码和访问口令要分开获取呢?
OAuth2 协议中,用户登录成功后,OAuth2 认证服务器会将用户的浏览器回调到一个回调地址,并携带一个授权码 code
。这个授权码 code
一般有效期十分钟且一次有效,用后作废。这避免了在前端暴露 access_token
或者用户信息的风险,access_token
的有效期都比较长,一般为 1~2 个小时。如果泄露会对用户造成一定影响。后端收到这个 code
之后,需要使用 Client Id + Client Secret + Code
去授权服务器换取用户的 access_token
。
在这一步,实际上授权服务器对第三方应用进行了认证,能够确保来授权服务器获取 access_token
的机器是可信任的,而不是任何一个人拿到 code
之后都能来授权服务器进行 code
换 token
。如果 code
被黑客获取到,如果他没有 Client Id + Client Secret
也无法使用,就算有,也要和真正的应用服务器竞争,因为 code
一次有效,用后作废,加大了攻击难度。相反,如果不经过 code
直接返回 access_token
或用户信息,那么一旦泄露就会对用户造成影响。
简单说就是,client secret 不能暴露给前端(验证 client),用户授权(获取 code)又只能前端做,因此需要分两步。
OIDC(OpenID Connect)
既然 OAuth 本身就隐含了身份验证,那么为什么不以标准化的形式将身份验证的结果导出,使得第三方应用可以使用呢?这就是 OIDC 要做的事情了。那身份验证的结果是什么?很简单,它就是用户的各种信息。
OIDC 怎么做?简单来说,就是在 OAuth 返回 access token
的时候顺带返回 id token
,id token
的格式是 JWT
,第三方应用可使用非对称公钥或者对称密码验证 id token
的合法性和有效性,而 id token
本身也包含了基本用户信息。另外,OIDC 提供了 UserInfo endpoint,第三方应用可携带 access token 访问该 endpoint 以获取额外的用户信息。
OIDC 还有一个好处,就是单点登录(SSO,Single Sign On)和单点注销(SLO,Single LogOut)。跟 OAuth 类似,OIDC 提供的集中化身份验证,它可以对应多个应用。只要用户成功登录了一个应用,那么当他登录其他应用的时候,就无需再进行一次身份验证了(例如输入用户名密码),那是因为授权服务器在用户的浏览器里面存下了 cookie。而单点注销则是用户注销了一个应用,其他应用也顺便注销了,注销既可以借由浏览器来做,也可以由第三方应用的后端与授权服务器之间来做。注销的时候指定的参数就是 id token
里面的 session 字段。
注意:OIDC 并没有指定身份验证的具体方式,例如传统的密码或者刷脸,而是指定了如何将身份验证委托给一个集中化的身份验证提供者,在身份验证通过后得到什么凭证(
id token
),这个凭证如何被校验(JWT 格式),这个凭证包含了哪些用户信息。这样第三方应用就无需重造轮子了。OAuth 提供了集中化的授权,而 OIDC 则是在此基础上进一步提供了集中化的身份验证。
APISIX 对 OAuth/OIDC 的支持
Apache APISIX 是一个开源的云原生 API 网关,作为 API 网关,它兼具动态、实时、高性能等特点,提供了负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。你可以使用 APISIX 来处理传统的南北向流量,以及服务间的东西向流量,也可以当做 K8s Ingress controller 来使用。
APISIX 既然是 API 网关,为多个上游应用服务器做代理,那么集中授权、集中身份认证,放在 API 网关是最自然不过的事情了。
APISIX 的 openid-connect
插件支持 OpenID Connect 协议,用户可以使用该插件让 APISIX 对接众多认证鉴权软件,如 Okta、Keycloak、Ory Hydra、Authing 等,作为集中式认证网关部署于企业中。OIDC是OAuth的超集,所以这个插件也隐含了对OAuth的支持。
部署图如下所示:
配置实例:使用 Keycloak 与 API 网关保护你的 API配置 Keycloak
信息 | 取值 |
---|---|
keycloak地址 | http://127.0.0.1:8080/ |
Realm | myrealm |
Client Type | OpenID Connect |
Client ID | myclient |
Client Secret | e91CKZQwhxyDqpkP0YFUJBxiXJ0ikJhq |
Redirect URI | http://127.0.0.1:9080/anything/callback |
Discovery | http://127.0.0.1:8080/realms/myrealm/.well-known/openid-configuration |
Logout URI | /anything/logout |
Username | myuser |
Password | myrealm |
Realm | mypassword |
场景示例
curl -XPUT 127.0.0.1:9080/apisix/admin/routes/1 -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -d '{"uri":"/anything/*","plugins": {"openid-connect": {"client_id": "myclient","client_secret": "e91CKZQwhxyDqpkP0YFUJBxiXJ0ikJhq","discovery": "http://127.0.0.1:8080/realms/myrealm/.well-known/openid-configuration","scope": "openid profile","bearer_only": false,"realm": "myrealm","redirect_uri": "http://127.0.0.1:9080/anything/callback","logout_path": "/anything/logout"}},"upstream":{"type":"roundrobin","nodes":{"httpbin.org:80":1}}
}'
创建 API 成功后访问 http://127.0.0.1:9080/anything/test 时,由于未进行登录,因此将被引导到 Keycloak 的登录页面:
输入账号(myuser)、密码(mypassword)完成登录后,成功跳转到 http://127.0.0.1:9080/anything/test 页面:
访问 http://127.0.0.1:9080/anything/logout 退出登录:
总结
本文介绍了 OAuth 协议由来和授权流程,引入更上一层的身份层协议 OIDC 并提供了详细的配置示例。 作为最流行的鉴权方式,OAuth/OIDC 通过 APISIX 的鉴权插件在 API 网关层面进行集中化鉴权管理,使得客户端和上游服务器之间免去重复繁琐的鉴权部署和维护。
相关文章:
关于 OAuth 你又了解哪些?
作者罗锦华,API7.ai 技术专家/技术工程师,开源项目 pgcat,lua-resty-ffi,lua-resty-inspect 的作者。 OAuth 的背景 OAuth,O 是 Open,Auth 是授权,也就是开放授权的意思。OAuth 始于 2006 年&a…...
18. 构造函数和析构函数,构造函数的分类和调用
构造函数和析构函数 构造函数 //没有返回值 不用写void//函数名 与 类名相同//可以有参数 ,可以发生重载//构造函数 由编译器自动调用一次 无须手动调用析构函数 //没有返回值 不用写void函数名 与类名相同 函数名前 加 ~不可以有参数 ,不可以发生重载析构函数 也是由编译器自…...
JavaScript设计模式es6(23种)
设计模式简介设计模式代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。设计模式是一套被反复使用的…...
设计「业务」与「技术」方案
三天研发,两天设计; 01【优先做设计方案】 职场中的那些魔幻操作,研发最烦的是哪个? 作为一个数年且资深的互联网普通开发,可以来说明一下为什么是:缺乏设计; 面对业务需求的时候,…...
C/C++:预处理(下)
目录 一.回顾程序的编译链接过程 二. 预处理之预定义#define 1.#define定义的标识符 2.#define定义的宏 3.带副作用的表达式作为宏实参 4.两个经典的宏 5.#define使用的一些注意事项小结 6.宏与函数的比较 7.#undef 附:关于#define的三个冷知识 三. 条件…...
2023互联网相关岗位转行与就业选择的简单分析
文章目录1、城市2、岗位1、城市 能找得到工作的城市,可能主要也就这些base了 2、岗位 主要技术岗位 Python 侧重人工智能,人工智能门槛高大家心知肚明。如果学python 不走人工智能,只走单纯的后端开发,不管从薪资还是岗位数量…...
LeetCode·每日一题·1223.掷骰子模拟·记忆化搜索
作者:小迅链接:https://leetcode.cn/problems/dice-roll-simulation/solutions/2103471/ji-yi-hua-sou-suo-zhu-shi-chao-ji-xiang-xlfcs/来源:力扣(LeetCode)著作权归作者所有。商业转载请联系作者获得授权࿰…...
【GPLT 二阶题目集】L2-043 龙龙送外卖
参考地址:AcWing 4474. 龙龙送外卖(杂题选讲) 作者:yxc 感谢y总! 龙龙是“饱了呀”外卖软件的注册骑手,负责送帕特小区的外卖。帕特小区的构造非常特别,都是双向道路且没有构成环 —— 你可以…...
Maven:基础知识
Maven概念图生命周期目录工程创建测试常用命令COMPILATION ERROR : 不再支持目标选项 5。请使用 7 或更高版本。问题解决pom.xml文件properties配置示例scope配置详解概念图 依赖管理构建项目Maven 的底层核心实现项目的构建和管理必须通过插件完成,但插件本身并不包…...
Web 框架 Flask 快速入门(一)flask基础与模板
前言 课程地址:Python Web 框架 Flask 快速入门 文章目录前言🌴 Flask基础和模板🌷 一个简单的flask程序🌼 模板的使用🌴 Flask基础和模板 1、web框架的作用 避免重复造轮子,app程序不必关心于服务器的沟…...
1CN/Jaccard/PA/AA/RA/Katz/PageRank/SimRank
common neighbors(CN) 公共邻居的数量。 Jaccard 用于比较有限样本集之间的相似性与差异性。Jaccard系数值越大,样本相似度越高。 preferential attachment(PA) 节点倾向于连接到节点度较高的节点上,&…...
YOLOv5-Backbone模块实现
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍦 参考文章地址: 365天深度学习训练营-第P8周:YOLOv5-Backbone模块实现🍖 作者:K同学啊一、前期准备1.设置GPUimport torch from torch impor…...
【C语言】程序环境和预处理
🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 小苏希望大家能从这篇文章中收获到许…...
9.关系查询处理和查询优化
其他章节索引 梳理 名词解释 代数优化:是指关系代数表达式的优化,也即按照一定规则,通过对关系代数表达式进行等价变换,改变代数表达式中操作的次序和组合,使查询更高效物理优化:是指存取路径和底层操作算…...
计算机组成原理(三)
5.掌握定点数的表示和应用(主要是无符号数和有符号数的表示、机器数的定点表示、数的机器码表示); 定点数:小数点位置固定不变。 定点小数:小数点固定在数值位与符号位之间; 定点整数:小…...
C. Least Prefix Sum codeforces每日一题
🚀前言 🚀 大家好啊,这里是幸麟 🧩 一名普通的大学牲,最近在学习算法 🧩每日一题的话难度的话是根据博主水平来找的 🧩所以可能难度比较低,以后会慢慢提高难度的 🧩此题标…...
ASEMI三相整流模块MDS100-16图片,MDS100-16尺寸
编辑-Z ASEMI三相整流模块MDS100-16参数: 型号:MDS100-16 最大重复峰值反向电压(VRRM):1600V 最大RMS电桥输入电压(VRMS):1700V 最大平均正向整流输出电流(IF&#…...
【第37天】斐波那契数列与爬楼梯 | 迭代的鼻祖,递推与记忆化
本文已收录于专栏🌸《Java入门一百例》🌸学习指引序、专栏前言一、递推与记忆化二、【例题1】1、题目描述2、解题思路3、模板代码4、代码解析5.原题链接三、【例题1】1、题目描述2.解题思路3、模板代码4、代码解析5、原题链接三、推荐专栏四、课后习题序…...
Map集合
Map集合 Map接口的简介 Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。 Map 没有继承 Collection 接口,…...
PyQt5编程扩展 3.2 资源文件的使用
目录 本例运行效果: 设计Qt窗体 建立项目 放一个Group Box 放三个Label 放一个Horizontal Slider 放两个Line Edit 层次结构 布局 放一个Group Box 放两个Label 放两个Line Edit 放一个Push Button 层次结构 布局 放一个frame 层次结构 布局 窗体…...
Linux系统之文件共享目录设置方法
Linux系统之文件共享目录设置方法一、本次实践目的二、检查本地系统环境1.检查系统版本2.检查系统内核三、创建相关用户及用户组1.创建共享目录2.创建测试用户账号3.创建用户组4.设置用户的属组5.查看admin和IT用户组成员6.查看所有用户信息四、共享目录权限设置1.设置/data/so…...
上海亚商投顾:三大指数均涨超1% 芯片板块集体大涨
上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。市场情绪三大指数今日低开高走,午后集体涨超1%,创业板指盘中涨超1.7%。芯片板块集体大涨,…...
Harbor私有仓库部署与管理
目录 前言 一、Harbor概述 二、Harbor 的特性 三、Harbor的构成 四、Harbor构建Docker私有仓库 1、环境配置 2、案例需求 3、部署Harbor服务 3.1、部署docker compose服务 3.2 下载或上传Harbor安装程序 3.3、启动Harbor 3.4、查看Harbor启动镜像 4、物理机访问se…...
互联网架构之 “高可用” 详解
一、什么是高可用 高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。 假设系统一直能够提供服务,我们说系统的可用性是100%。 如果系统每运行…...
分布式高级篇4 —— 商城业务(2)
一、订单服务1、订单基本概念2、订单基本构成3、订单状态4、订单流程5、配置拦截器拦截订单请求6、订单确认页模型抽取7、订单确认页vo封装8、Feign 远程调用请求头丢失问题\*\*\*\*\* 惨痛教训9、Feign 异步调用请求头丢失问题10、查看库存状态11、模拟计算运费12、接口幂等性…...
二分查找基本原理
二分查找基本原理1.二分查找1.1 基本概念1.2 二分查找查找步骤1.2.1 中间索引不能整除,取整数作为中间索引1.2.2 索引不能整除,整数1作为中间索引1.3 二分查找大O记法表示2. 二分查找代码实现1.二分查找 1.1 基本概念 二分法(折半查找)是一…...
【Python实战案例】Python3网络爬虫:“可惜你不看火影,也不明白这个视频的分量......”m3u8视频下载,那些事儿~
前言 哈喽!上午好嘞,各位小可爱们!有没有等着急了呀~ 由于最近一直在学习新的内容,所以耽搁了一下下,抱歉.jpg 双手合十。 所有文章完整的素材源码都在👇👇 粉丝白嫖源码福利,请移…...
UE4:使用样条生成随机路径,并使物体沿着路径行走
一、关于样条的相关知识 参考自:样条函数 - 馒头and花卷 - 博客园 三次样条(cubic spline)插值 - 知乎 B-Spline(三)样条曲线的性质 - Fun With GeometryFun With Geometry 个人理解的也不是非常深,但是大概要知道的就是样条具…...
计算机组成原理(判断题)
计算机控制器是根据事先编好的程序,根据其指令来进行控制只会每一步骤的操作; 面向主存的双总线结构计算机系统,因在CPU与主存之间增加了一组存储器总线,由于通过存储器总线访存,提高了CPU的访存速度,也减轻…...
error: failed to push some refs to ... 就这篇,一定帮你解决
目录 一、问题产生原因 二、解决办法 三、如果还是出问题,怎么办?(必杀) 一、问题产生原因 当你直接在github上在线修改了代码,或者是直接向某个库中添加文件,但是没有对本地库同步,接着你想…...
江苏专业网站建设公司电话/跨境电商怎么做
目的: 代码的重构!我上一次写的随笔“C#学习——序列化和反序列化”对接口的理解似乎有误,接口基本上没进行什么设计,之后虽然也重新设计了一下, 但是写了两个接口IDeserialize和ISerialize每个接口里面只有一方法&…...
超星网站开发实战答案/自媒体平台注册入口
Trojan-PSW.Win32.QQPass.je分析报告安天实验室 CERT一、 病毒标签:病毒名称: Trojan-PSW.Win32.QQPass.je 病毒类型: ***类 文件 MD5: BEA3C452B98DF949026B149234DFCED8 公开范围: 完全公开 危害等级: 3 …...
wordpress支持中文用户名/今日头条指数查询
"The secret of change is to focus all of your energy, not on fighting the old but on building the new.—— Dan Millman"请问视图是什么?视图相关语句有哪些?视图在什么场景下使用?夺命三连更多精彩文章请关注公众号『Pytho…...
淄博企业网站建设公司/百度有人工客服吗
我这里是要做这样的效果的 首先我想到是用行内元素(使用span和i),哈哈哈,然后那个橙色的小点点又要有宽高,所以只能给定义成inline-block,其实使用什么属性的元素都没关系,但具体是怎么样无论页面宽度怎么变化&#x…...
网站建设怎么制作网站/镇江网站建设企业
2019独角兽企业重金招聘Python工程师标准>>> //初始化textfield并设置位置及大小 UITextField *text [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 130, 30)]; //设置边框样式,只有设置了才会显示边框样式 text.borderStyle UITextBorderS…...
企业注册登记/seo查询seo
在.h文件的类声明外面定义 typedef struct _SelectItemsInfo { CString str1; CString str2; }Select, *PSelect; 在.h文件的类中声明 std::vector<PSelect> m_pVecSelect; //保存结构体指针到vector 注意一定要有std::不然后报错 然后在.cpp文件中使用 P…...