【全栈修炼】OAuth2 修炼宝典

一、OAuth 概念

开放授权(OAuth)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。 —— 维基百科

严格来说,OAuth2 不是一个标准协议,而是一个安全的授权框架。其详细描述系统中不同角色,用户,服务前端应用(如 API )以及客户端(如网站或APP)之间如何实现相互认证

当前 OAuth 协议版本是 OAuth2.0,需要注意的是,OAuth2.0 并不向下兼容 OAuth1.0。

在生活中,比较常见的 OAuth2 的使用场景是授权登录,并且也广泛应用于 web、桌面应用和移动 APP 的第三方服务提供授权登录验证机制,以实现不同应用直接数据访问的权限

二、OAuth2 重点名词介绍

在 OAuth2 标准中定义了以下四种角色:

  • 资源拥有者 (Resource Owner):

代表授权客户端访问本身资源信息的用户(User);

  • 客户端 (Client):

代表意图访问受限资源的第三方应用。

  • 资源服务器 (Resource Server):

代表托管了受保护的用户账号信息的服务器,它与认证服务器,可以是同一台服务器,也可以是不同的服务器;

  • 授权服务器 (Authorization Server):

代表验证用户身份然后为客户端派发资源访问令牌的服务器,即服务提供商专门用来处理认证的服务器;

三、OAuth2 运行流程

1. 流程分析

20191028-OAuth2-01.png

(配图来自阮一峰大佬

大致流程概括就是:

  • (A)Authrization Request

用户打开客户端以后,客户端要求用户给予授权。

  • (B)Authorization Grant(Get)

用户同意给予客户端授权。

  • (C)Authorization Grant(Post)

客户端向授权服务器发送它自己的客户端身份标识和上一步中获得的授权(authorization grant),向认证服务器申请令牌。

  • (D)Access Token(Get)

认证服务器对客户端进行认证以后,确认无误,同意发放令牌(access token),授权阶段至此全部结束。

  • (E)Access Token(Post && Validate)

客户端使用令牌,向资源服务器申请获取资源。

  • (F)Protected Resource(Get)

资源服务器确认令牌无误,同意向客户端开放资源。

理解完上面整个流程以后,我们再看看下面这张图,能更加清晰理解 OAuth2 的整个运行流程:

20191028-OAuth2-02.png

(配图来自公众号前端修仙之路

从整个流程可以看出,在 B 步骤最为关键,即需要获取到用户对客户端的授权(如我们在微信扫码登录时,点击“确定”按钮的步骤)。

有了这个授权以后,客户端才能拿到令牌,进而凭令牌向资源服务器获取资源。

2. 案例:微信登录

另外,微信登录的实现流程也类似:

20191028-OAuth2-03.png

(配图来自微信官方文档

其整体流程为:

  1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据 code 参数;

  2. 通过 code 参数加上 AppIDAppSecret 等,通过 API 换取 access_token

  3. 通过 access_token 进行接口调用,获取用户基本数据资源或帮助用户实现基本操作

3. OAuth2 优缺点

  • 优点:

适合快速开发实施,代码量少,API需要被不同APP使用,且每个APP使用方式也不同的情况。

  • 缺点:

学习和理解的成本比较大,并且 OAuth2 不是一个严格的标准协议,在实施过程中更容易出错。

四、OAuth2 四种授权模式

通过前面描述,可以知道OAuth 的核心就是向第三方应用颁发令牌。

OAuth 2.0 规定了四种获得令牌的流程。你可以选择最适合自己的那一种,向第三方应用颁发令牌。即以下四种授权方式:

  • 授权码(authorization-code)
  • 隐藏式(implicit)
  • 密码式(password)
  • 客户端凭证(client credentials)

注意:

不管哪一种授权方式,第三方应用申请令牌之前,都必须先到系统备案,说明自己的身份,然后会拿到两个身份识别码:客户端 ID(client ID)客户端密钥(client secret)

这是为了防止令牌被滥用,没有备案过的第三方应用,是不会拿到令牌的。

1. 授权码(authorization code)

第三方应用先申请一个授权码,然后再用该码获取令牌

适用于有后端的 Web 应用,授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。

这种方式也是最常用的流程,安全性最高

整体流程

20191028-OAuth2-04.png

(配图来自阮一峰大佬

步骤分析

  1. 用户从 A 网站跳转到 B 网站,请求用户确认授权,以获取授权码,其发送链接示意如下:
https://b.com/oauth/authorize?
       response_type=code&
       client_id=CLIENT_ID&
       redirect_uri=CALLBACK_URL&
       scope=read

其中:

response_type 参数表示要求返回授权码(code);

client_id 参数让 B 知道是谁在请求;

redirect_uri 参数是 B 接受或拒绝请求后的跳转网址;

scope 参数表示要求的授权范围(这里是只读);

  1. 在 B 网站中,当用户同意授权 A 网站,则 B 网站会携带授权码,重定向到 redirect_uri 参数指定的网址,就像下面这样:
https://a.com/callback?code=AUTHORIZATION_CODE
  1. A 网站获取授权码以后,在 A 网站后端中向 B 网站请求令牌:
https://b.com/oauth/token?
       client_id=CLIENT_ID&
       client_secret=CLIENT_SECRET&
       grant_type=authorization_code&
       code=AUTHORIZATION_CODE&
       redirect_uri=CALLBACK_URL

client_id 参数和 client_secret 参数用来让 B 确认 A 的身份( client_secret 参数是保密的,因此只能在后端发请求);

grant_type 参数的值是 AUTHORIZATION_CODE ,表示采用的授权方式是授权码;

code 参数是上一步拿到的授权码;

redirect_uri 参数是令牌颁发后的回调网址;

  1. B 网站接受请求并验证身份,身份验证通过后,会发放令牌。向redirect_uri 指定的网址,发送包含令牌 access_token 字段的JSON数据,流程完毕。

2. 隐藏式(implicit)

隐藏授权码步骤,直接向前端发放令牌,也称授权码隐藏式。

整体流程

20191028-OAuth2-05.png

(配图来自阮一峰大佬

步骤分析

  1. 用户从 A 网站跳转到 B 网站,要求授权用户数据给 A 网站使用。
https://b.com/oauth/authorize?
  response_type=token&
  client_id=CLIENT_ID&
  redirect_uri=CALLBACK_URL&
  scope=read

response_type 参数为 token,表示要求直接返回令牌

  1. 用户在 B 网站同意授权给 A 网站。

当用户同意授权后,会跳转到 redirect_uri 参数指定的重定向地址,并将令牌作为 URL 参数传递给 A 网站。

https://a.com/callback#token=ACCESS_TOKEN

token 参数就是令牌,A 网站因此直接在前端拿到令牌。

注意:

这里的令牌位置是 URL 锚点(即 # 号),而不是查询字符串,这是因为锚点不会发到服务器,避免泄露令牌的风险。

适用场景:

由于直接传递令牌不安全,因此常常适用在对安全要求不高的场景,并且令牌有效期非常短,例如会话期间(session)有效,关闭浏览器便失效。

3. 密码式(password)

即:对于信任的应用,可以携带约定的用户名和密码进行令牌申请

流程分析

20191028-OAuth2-07.png
  1. A 网站使用 B 网站提供的用户名和密码,向 B 网站发起令牌请求。
https://oauth.b.com/token?
  grant_type=password&
  username=USERNAME&
  password=PASSWORD&
  client_id=CLIENT_ID

grant_type 参数是授权方式,这里的 password 表示"密码式";
usernamepassword 是 B 的用户名和密码。

  1. B 网站验证身份后直接将令牌存在 JSON 数据中,作为 HTTP 相应返回令牌给 A 网站。

适用场景:

风险较大,一般适用在对应用高度信任的情况。

4. 客户端凭证(client credentials)

即:给出凭证让对方确认并提供令牌

流程分析

  1. A 应用在命令行向 B 发出请求。
https://oauth.b.com/token?
  grant_type=client_credentials&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET

grant_type 参数等于 client_credentials 表示采用凭证式;
client_idclient_secret 用来让 B 确认 A 的身份。

  1. B 网站验证身份后返回令牌。

这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。

适用场景:

通过命令行请求令牌。

流程分析

20191028-OAuth2-06.png

五、使用令牌

当网站获取到令牌以后,接下来每个 API 请求都需要带上令牌,其做法是在请求的头信息中,将令牌添加 Authorization 字段中。

六、更新令牌

当令牌有效期到了,OAuth2 允许用户自动更新令牌,而不用让用户重新授权获取新令牌。

具体流程:

在 B 网站发放令牌时,一次性发放 2 个令牌,一个用于获取数据,一个用于获取新的令牌(refresh token 字段)。令牌到期后,用户使用 refresh token 发送请求去更新令牌:

https://b.com/oauth/token?
  grant_type=refresh_token&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET&
  refresh_token=REFRESH_TOKEN

grant_type 参数为 refresh_token 表示要求更新令牌;
client_id 参数和 client_secret 参数用于确认身份;
refresh_token 参数就是用于更新令牌的令牌。

B 网站验证通过以后,就会颁发新的令牌。

参考文章

  1. 部门内部培训资料
  2. 《OAuth 2 深入介绍》
  3. 《阮一峰 理解OAuth 2.0》
  4. 《阮一峰 OAuth 2.0 的四种方式》

关于我

本文首发在 pingan8787个人博客,如需转载请联系本人。

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推荐 https://github.com/pingan8787/Leo_Reading/issues
ES小册 js.pingan8787.com

微信公众号

bg
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • OAuth2.0 是关于授权的开放网络标准,它允许用户已第三方应用获取该用户在某一网站的私密资源,而无需提供用户名...
    baiyi阅读 9,933评论 4 25
  • 原文地址:http://www.sanjinbest.com/blog/b6ec839d56c04ca387b95...
    木子小三金阅读 8,462评论 0 37
  • Spring OAuth2.0 提供者实现原理: Spring OAuth2.0提供者实际上分为: 授权服务 Au...
    EnchIGo阅读 1,154评论 0 5
  • 1. 介绍 OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUT...
    带刀打天下阅读 354评论 0 1
  • 什么是三方授权? 第三方授权就是,委托第三方来对既定的用户进行鉴定,鉴定成功之后,下发信任凭证,信任凭证和用户挂钩...
    一只小哈阅读 32,207评论 2 21