by 太阳雪html
咱们常常看到或者用到一些可使用微博、微信、支付宝等帐号登陆的应用,还有一些微博助手、微信公众号助手、客户端之类的东西,这些是怎么作的呢,背后的原理是什么呢?为何公众号配置起来那么繁琐呢?什么是 access token、refresh token?等等,今天咱们来了解下开放式受权模式 OAuthpython
随着互联网的发展,各类应用相互交叉,处处须要用户登陆,信息安全成为了避免可回避的问题,应用须要扩展,用户须要更好的体验,信息须要更安全的保障,为了知足这些需求,互联网技术不断推陈出新,从通讯安全,到各类协议框架,有无数的解决方案。编程
其中 OAuth 框架是很闪耀的一个,一经推出,就获得各大互联网公司的积极响应,到2010年推出了 OAuth 2.0, 不但修补了 1.0 的安全漏洞,并且简化了受权流程,获得更普遍的应用,成为了主流。从 PC 到 Web,从移动端到物联网,愈来愈多的应用构建在 OAuth 框架之上,那么 OAuth 是什么呢?浏览器
OAuth 框架提供了一种认证和受权机制,可让用户将其受保护的资源受权给其余应用来访问或者使用。缓存
阮一峰老师对 受权有个形象比喻:受权机制至关于你给快递员一个临时密码(受权),快递员可使用这个密码打开小区门禁,将快递送到你家门口,然后零时密码将失效(详见参考连接)。安全
这个例子中,你就是 用户
,小区是 受保护的资源
,快递员是其余应用(第三方应用
)。服务器
若是没有这个机制:微信
有了 OAuth 框架(协议),既方便,又安全网络
这里不打算介绍 OAuth 1.0,缘由是:app
若是想了解更多关于 OAuth 的知识,请访问参考连接
OAuth2.0 实际上就是让第三方服务得到用户在资源服务器上的受权的过程,会涉及到 4 种角色
Resource owner
),即用户Authorization server
),用来认证用户凭证,颁布受权码的服务器Resource Server
),存放用户受保护的资源的服务器Client
),也称之为客户端(后续皆称 客户端),须要获得用户受权,以便访问用户受保护的资源的应用程序不是任何客户端都能获得受权的,在开通 OAuth 受权以前,须要先到认证服务器或者资源服务器上注册,注册成功会获得
appid
和app_secret
,用来向认证服务器代表应用的身份
了解了 OAuth2.0 框架中的主要角色,有必要了解下角色之间关联关系
appid
和 app_secret
,做为客户端和服务商的交互凭证至此,四个角色之间的关联就创建好了,下面开始介绍具体的受权方式
没有比图更能说明白流程的,借用 RFC6749 文档中的图:
Access Token
,便可以访问资源的令牌Access Token
请求资源服务器上的资源Access Token
后,返回受保护的资源流程中最核心的是让客户端得到 Access Token
,以后在访问受保护资源是,就不须要用户反复受权了
Access Token
显然不是用户在资源服务器上的密码,是有认证服务器颁发的,那么也能够被销毁
Access Token
和以前课程中的 JWT 是相似的,实际上 JWT 是 OAuth 认证的一个特例
根据受权流程,OAuth2.0 定义了 4 种针对不一样应用场景的受权模式
受权码模式是最完整,安全性最高的受权模式,也是最经常使用的一种模式,其特色是经过客户端的后台服务器与认证服务器交互,如图:
注意:上图中的步骤 A, B, C 在经过用户代理端( User-Agent 通常指浏览器)时,被拆分红了两部分
接下来讲明一下过程当中所包含一下参数
不一样认证服务器上的参数名称有可能不一样,但含义相同,例如
client_id
通常被appid
代替
步骤 A,客户端申请认证的 URI,包含如下参数:
response_type
:表示受权类型,必选项,此处的值固定为 code
,由于须要先获取受权码client_id
:表示客户端的ID,必选项,是在认证服务器分配给客户端的id,即 appidredirect_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
数据,且不容许作缓存,以提升安全性
简化模式不须要经过客户端后台服务器,直接在浏览器中向认证服务器申请令牌,跳过了受权码
这个步骤,所以得名。全部步骤在浏览器中完成,令牌对访问者是可见的,且客户端不须要认证,如图:
重定向URI
,并在URI的Hash部分包含了访问令牌 access_token
接下来讲明一下过程当中所包含一下参数
步骤 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 信息等
这里也只简单介绍下,若有兴趣了解,能够查阅文末参考
在 受权码模式中,受权服务器能够会同时返回 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,即第三方应用在受权服务器上注册被分配的 idclient_secret
: 客户端和受权服务器通行的密钥,有受权服务器颁发,在特殊须要确认的状况下须要做为验证条件refresh_token
: 用户获取新的 access_token
的 refresh_token
上面较为详细的讲述了 OAuth2.0 框架,了解了在开放网络中如何安全的获取用户受权的技术细节,但再完善的交互方案、再复杂的严密的通讯过程,都避免不了中间人攻击,当客户端和认证服务器之间经过 http 协议交互数据时,会被截取通讯内容,从而得到用户的受权,这是不能接受的,因此 OAuth2.0 须要创建在 https 协议上,将通讯内容加密,最大程度的防止信息被窃取。
若是 OAuth2.0 框架用在敏感信息交互上时,必须使用 https 协议确保安全,但并非说只能支持 https,对于非敏感数据,或者不重要的受权,可使用 http 协议做为通讯方式
本节课程着重介绍了 OAuth2.0 受权框架,从它的做用,到具体的技术细节,作了较为详细的讲述,若是须要用安全的受权,须要将通讯创建在 https 协议之上。因为 OAuth 概念较多,流程复杂,这节没有涉及到具体的编程实践,下一节,咱们以 Github 为例,使用以前介绍过的 Authlib 模块,用 Flash 实现一个第三方应用,做为实践,敬请期待
参考
关注公众号:python技术,回复"python"一块儿学习交流