第87天: OAuth2.0 简介

by 太阳雪html

咱们常常看到或者用到一些可使用微博、微信、支付宝等帐号登陆的应用,还有一些微博助手、微信公众号助手、客户端之类的东西,这些是怎么作的呢,背后的原理是什么呢?为何公众号配置起来那么繁琐呢?什么是 access token、refresh token?等等,今天咱们来了解下开放式受权模式 OAuthpython

随着互联网的发展,各类应用相互交叉,处处须要用户登陆,信息安全成为了避免可回避的问题,应用须要扩展,用户须要更好的体验,信息须要更安全的保障,为了知足这些需求,互联网技术不断推陈出新,从通讯安全,到各类协议框架,有无数的解决方案。编程

其中 OAuth 框架是很闪耀的一个,一经推出,就获得各大互联网公司的积极响应,到2010年推出了 OAuth 2.0, 不但修补了 1.0 的安全漏洞,并且简化了受权流程,获得更普遍的应用,成为了主流。从 PC 到 Web,从移动端到物联网,愈来愈多的应用构建在 OAuth 框架之上,那么 OAuth 是什么呢?浏览器

OAuth 是什么

OAuth 框架提供了一种认证和受权机制,可让用户将其受保护的资源受权给其余应用来访问或者使用。缓存

阮一峰老师对 受权有个形象比喻:受权机制至关于你给快递员一个临时密码(受权),快递员可使用这个密码打开小区门禁,将快递送到你家门口,然后零时密码将失效(详见参考连接)。安全

这个例子中,你就是 用户,小区是 受保护的资源,快递员是其余应用(第三方应用)。服务器

若是没有这个机制:微信

  • 要么你就得去小区门口拿快递,不方便,
  • 要么就得告诉全部可能给你送快递的快递员门禁密码,不安全

有了 OAuth 框架(协议),既方便,又安全网络

OAuth2.0

这里不打算介绍 OAuth 1.0,缘由是:app

  • OAuth 1.0 存在安全漏洞
  • OAuth 1 和 后面的 OAuth 1a 交流流程比较复杂
  • OAuth 2.0 安全性好,应用更普遍

若是想了解更多关于 OAuth 的知识,请访问参考连接

角色

OAuth2.0 实际上就是让第三方服务得到用户在资源服务器上的受权的过程,会涉及到 4 种角色

  • 资源拥有者(Resource owner),即用户
  • 认证服务器(Authorization server),用来认证用户凭证,颁布受权码的服务器
  • 资源服务器(Resource Server),存放用户受保护的资源的服务器
  • 第三方应用(Client),也称之为客户端(后续皆称 客户端),须要获得用户受权,以便访问用户受保护的资源的应用程序

不是任何客户端都能获得受权的,在开通 OAuth 受权以前,须要先到认证服务器或者资源服务器上注册,注册成功会获得 appidapp_secret,用来向认证服务器代表应用的身份

角色之间关联

了解了 OAuth2.0 框架中的主要角色,有必要了解下角色之间关联关系

  • 认证服务器 和 资源服务器:
    一般来讲,认证服务器和资源服务器同属于一个服务商,它们就有天生的关联,并且是内部的安全的,甚至它们能够部署在同一个服务器(Web 服务器)上
  • 用户 和 服务商:
    对于像 Github、微信这样的知名应用,用户会主动在这些应用或服务上注册,填写的资料信息,设置的昵称,产生的文章、上传的照片,等等将成为用户的资源,这些资源被存放在资源服务器上
  • 客户端 和 服务商:
    客户端,即第三方应用,要从服务商的资源服务器中获取数据,给用户提供额外服务,必须在服务商处注册,提供应用的基本信息,认证信息,服务域名,申请用户受权的范围、甚至企业资质(例如申请微信公众号的企业服务)等等,申请经过后,服务商会返回 appidapp_secret,做为客户端和服务商的交互凭证
  • 用户 和 客户端:客户端提供了特别的服务,能够吸引到用户,为了让用户体验更好,引导用户经过受权的方式,从而获取受权范围内的用户信息,例如 Openid,做为用户在客户端上的惟一标识,从而创建起和用户的关联

至此,四个角色之间的关联就创建好了,下面开始介绍具体的受权方式

基本受权流程

没有比图更能说明白流程的,借用 RFC6749 文档中的图:

受权流程图

  • A 客户端,向用户发出受权请求
  • B 用户赞成或者拒绝客户端的受权请求,假设是赞成
  • C 客户端拿着用户的受权请求认证服务器作认证
  • D 若是 C 经过认证,认证服务器将返回 Access Token,便可以访问资源的令牌
  • E 客户端使用 Access Token 请求资源服务器上的资源
  • F 资源服务器验证了 Access Token 后,返回受保护的资源

流程中最核心的是让客户端得到 Access Token,以后在访问受保护资源是,就不须要用户反复受权了

Access Token 显然不是用户在资源服务器上的密码,是有认证服务器颁发的,那么也能够被销毁

Access Token 和以前课程中的 JWT 是相似的,实际上 JWT 是 OAuth 认证的一个特例

受权模式

根据受权流程,OAuth2.0 定义了 4 种针对不一样应用场景的受权模式

  • 受权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

受权码模式

受权码模式是最完整,安全性最高的受权模式,也是最经常使用的一种模式,其特色是经过客户端的后台服务器与认证服务器交互,如图:

受权码模式流程图

注意:上图中的步骤 A, B, C 在经过用户代理端( User-Agent 通常指浏览器)时,被拆分红了两部分

  • A 用户访问客户端的客户端,后者将前者导向认证服务器
  • B 用户肯定是否受权给客户端
  • C 假设用户给予受权,认证服务器将用户导向客户端事先指定的"重定向URI"(Redirection URI),同时附上一个受权码
  • D 客户端收到受权码,经过后台服务器,附上早先的"重定向URI",向认证服务器申请令牌。这一步对用户不可见
  • E 认证服务器核对了受权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)

接下来讲明一下过程当中所包含一下参数

不一样认证服务器上的参数名称有可能不一样,但含义相同,例如 client_id 通常被 appid 代替

步骤 A,客户端申请认证的 URI,包含如下参数:

  • response_type:表示受权类型,必选项,此处的值固定为 code,由于须要先获取受权码
  • client_id:表示客户端的ID,必选项,是在认证服务器分配给客户端的id,即 appid
  • redirect_uri:表示重定向URI,可选项
  • scope:表示申请的权限范围,可选项
  • state:表示客户端的当前状态,能够指定任意值,认证服务器会原封不动地返回这个值

步骤 C,认证服务器回应的 URI,包含如下参数:

  • code:表示受权码,必选项。该码的有效期应该很短,一般设为 10 分钟,客户端只能使用该码一次,不然会被认证服务器拒绝。该码与客户端 ID 和重定向 URI,是一一对应关系
  • state:若是客户端的请求中包含这个参数,认证服务器的回应也必须如出一辙包含这个参数

步骤 D,客户端向认证服务器申请令牌的 HTTP 请求,包含如下参数:

  • grant_type:表示使用的受权模式,必选项,此处的值固定为 authorization_code
  • code:表示上一步得到的受权码,必选项
  • redirect_uri:表示重定向 URI,必选项,且必须与 A 步骤中的该参数值保持一致
  • client_id:表示客户端 ID,必选项

步骤 E,认证服务器发送的 HTTP 响应,包含如下参数:

  • access_token:表示访问令牌,必选项
  • token_type:表示令牌类型,该值大小写不敏感,必选项,能够是bearer类型或mac类型
  • expires_in:表示过时时间,单位为秒。若是省略该参数,必须其余方式设置过时时间
  • refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项
  • scope:表示权限范围,若是与客户端申请的范围一致,此项可省略

认证服务器会以 JSON 的形式返回 access_token 数据,且不容许作缓存,以提升安全性

简化模式

简化模式不须要经过客户端后台服务器,直接在浏览器中向认证服务器申请令牌,跳过了受权码这个步骤,所以得名。全部步骤在浏览器中完成,令牌对访问者是可见的,且客户端不须要认证,如图:

简化模式流程图

  • A 客户端将用户导向认证服务器
  • B 用户决定是否给于客户端受权
  • C 假设用户给予受权,认证服务器将用户导向客户端指定的重定向URI,并在URI的Hash部分包含了访问令牌 access_token
  • D 浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值
  • E 资源服务器返回一个网页,其中包含的代码能够获取Hash值中的令牌
  • F 浏览器执行上一步得到的脚本,提取出令牌
  • G 浏览器将令牌发给客户端

接下来讲明一下过程当中所包含一下参数

步骤 A,客户端发送 HTTP 请求,包含的参数:

  • response_type:表示受权类型,此处的值固定为 token,必选项
  • client_id:表示客户端的ID,必选项
  • redirect_uri:表示重定向的URI,可选项
  • scope:表示权限范围,可选项
  • state:表示客户端的当前状态,能够指定任意值,认证服务器会原封不动地返回这个值

步骤 C,认证服务器回应客户端的 URI,包含如下参数:

  • access_token:表示访问令牌,必选项。
  • token_type:表示令牌类型,该值大小写不敏感,必选项
  • expires_in:表示过时时间,单位为秒。若是省略该参数,必须其余方式设置过时时间
  • scope:表示权限范围,若是与客户端申请的范围一致,此项可省略
  • state:若是客户端的请求中包含这个参数,认证服务器的回应也必须如出一辙包含这个参数

有个须要注意的地方,步骤 C,返回的 access_token 放在重定向 URL 的 Fragment 中,即锚点中, # 后面,例如

http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA
  &state=xyz&token_type=example&expires_in=3600

由于锚点中的内容不会发送给后台,从而减小了一次数据传输,下降了必定风险

对于简化模式得到的 access_token 有效期很短,通常是会话级的,即当会话结束时就失效

密码模式

密码模式中,用户向客户端提供本身的用户名和密码,客户端使用这些信息,向"服务商提供商"索要受权。

在这种模式中,用户必须把本身的密码给客户端,可是客户端不得储存密码(既然用户信任你,你就必须兑现这个承诺)。

密码模式的特性决定,须要用在用户对客户端高度信任的状况下,好比客户端是操做系统的一部分,或者由一个著名公司出品,而认证服务器只有在其余受权模式没法执行的状况下,才能考虑使用这种模式

这里只简单介绍下,不作作详细讲解,若有兴趣了解,能够查阅文末参考

客户端模式

客户端模式指客户端以本身的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于 OAuth 框架所要解决的问题

在这种模式中,用户直接向客户端注册,客户端以本身的名义要求"服务提供商"提供服务,其实不存在受权问题

客户端模式,就像二道贩子(只为借用比喻,并没有贬义),将原始服务包装后,再提供给最终用户,常见于多租户的 Saas 系统,例如统一提供支付通道、处理 GPS 信息等

这里也只简单介绍下,若有兴趣了解,能够查阅文末参考

刷新 access_token

在 受权码模式中,受权服务器能够会同时返回 refresh_token,用来在 access_token 过时前,从新获取新的 access_token,不须要用户从新确认受权,有助于提升用户体验

在 access_token 过时前,客户端可用 refresh_token 想受权服务器发送请求,例如,假设 b.com 是受权服务器地址,请求大致是:

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: 客户端 id,即第三方应用在受权服务器上注册被分配的 id
  • client_secret: 客户端和受权服务器通行的密钥,有受权服务器颁发,在特殊须要确认的状况下须要做为验证条件
  • refresh_token: 用户获取新的 access_tokenrefresh_token

安全的 OAuth2.0

上面较为详细的讲述了 OAuth2.0 框架,了解了在开放网络中如何安全的获取用户受权的技术细节,但再完善的交互方案、再复杂的严密的通讯过程,都避免不了中间人攻击,当客户端和认证服务器之间经过 http 协议交互数据时,会被截取通讯内容,从而得到用户的受权,这是不能接受的,因此 OAuth2.0 须要创建在 https 协议上,将通讯内容加密,最大程度的防止信息被窃取。

若是 OAuth2.0 框架用在敏感信息交互上时,必须使用 https 协议确保安全,但并非说只能支持 https,对于非敏感数据,或者不重要的受权,可使用 http 协议做为通讯方式

总结

本节课程着重介绍了 OAuth2.0 受权框架,从它的做用,到具体的技术细节,作了较为详细的讲述,若是须要用安全的受权,须要将通讯创建在 https 协议之上。因为 OAuth 概念较多,流程复杂,这节没有涉及到具体的编程实践,下一节,咱们以 Github 为例,使用以前介绍过的 Authlib 模块,用 Flash 实现一个第三方应用,做为实践,敬请期待

参考

关注公众号:python技术,回复"python"一块儿学习交流

相关文章
相关标签/搜索