一张图搞定OAuth2.0
1、引言
本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式
非常简单的一件事情,网上一堆神乎其神的讲解,让我不得不写一篇文章来终结它们。
一项新的技术,无非就是了解它是什么,为什么,怎么用。至于为什么,本篇文章不做重点探讨,网上会有各种文章举各种什么丢钥匙、发船票的例子供你去阅读,个人认为还是有些哗众取宠,没有聊到本质。
那我们就重点聊聊OAuth2.0是什么,怎么用。但首先在读本文之前,你要先对OAuth2.0有一定的了解,建议先读一下阮一峰的oauth2.0文章,直接看“授权码模式”即可,带着疑问再来读本文效果更好。
http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
2、OAuth2.0是什么
OAuth2.0是什么——豆瓣和QQ的故事
OAuth简单说就是一种授权的协议,只要授权方和被授权方遵守这个协议去写代码提供服务,那双方就是实现了OAuth模式。
简单说,OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。
举个例子,你想登录豆瓣去看看电影评论,但你丫的从来没注册过豆瓣账号,又不想新注册一个再使用豆瓣,怎么办呢?不用担心,豆瓣已经为你这种懒人做了准备,用你的qq号可以授权给豆瓣进行登录,请看。
第一步:在豆瓣官网点击用qq登录
第二步:跳转到qq登录页面输入用户名密码,然后点授权并登录
第三步:跳回到豆瓣页面,成功登录
这几秒钟之内发生的事情,在无知的用户视角看来,就是在豆瓣官网上输了个qq号和密码就登录成功了。在一些细心的用户视角看来,页面经历了从豆瓣到qq,再从qq到豆瓣的两次页面跳转。但作为一群专业的程序员,我们还应该从上帝视角来看这个过程。
OAuth2.0是什么——上帝视角
简单来说,上述例子中的豆瓣就是客户端,QQ就是认证服务器,OAuth2.0就是客户端和认证服务器之间由于相互不信任而产生的一个授权协议。呵呵,要是相互信任那QQ直接把自己数据库给豆瓣好了,你直接在豆瓣输入qq账号密码查下数据库验证就登陆呗,还跳来跳去的多麻烦。
先上一张图,该图描绘了只几秒钟发生的所有事情用上帝视角来看的流程
就这这张图,来说一下上述例子中的三个步骤在图中的表现。所用到的请求路径名称都是虚构的,所附带的请求参数忽略了一些非重点的。
如想了解每次的请求和响应的标准齐全的参数,还是去读那篇阮一峰的文章。http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
第一步:在豆瓣官网点击用qq登录
当你点击用qq登录的小图标时,实际上是向豆瓣的服务器发起了一个 http://www.douban.com/leadToAuthorize 的请求,豆瓣服务器会响应一个重定向地址,指向qq授权登录
浏览器接到重定向地址 http://www.qq.com/authorize?callback=www.douban.com/callback ,再次访问。并注意到这次访问带了一个参数是callback,以便qq那边授权成功再次让浏览器发起这个callback请求。不然qq怎么知道你让我授权后要返回那个页面啊,每天让我授权的像豆瓣这样的网站这么多。
至于访问这个地址之后,qq那边做出怎样的回应,就是第二步的事情了。总之第一步即对应了图中的这些部分。
第二步:跳转到qq登录页面输入用户名密码,然后点授权并登录
上一步中浏览器接到重定向地址并访问 http://www.qq.com/authorize?callback=www.douban.com/callback
qq的服务器接受到了豆瓣访问的authorize,在次例中所给出的回应是跳转到qq的登录页面,用户输入账号密码点击授权并登录按钮后,一定还会访问qq服务器中校验用户名密码的方法,若校验成功,该方法会响应浏览器一个重定向地址,并附上一个code(授权码)。由于豆瓣只关心像qq发起authorize请求后会返回一个code,并不关心qq是如何校验用户的,并且这个过程每个授权服务器可能会做些个性化的处理,只要最终的结果是返回给浏览器一个重定向并附上code即可,所以这个过程在图中并没有详细展开。现把展开图画给大家。
第三步:跳回到豆瓣页面,成功登录
这一步背后的过程其实是最繁琐的,但对于用户来说是完全感知不到的。用户在QQ登录页面点击授权登陆后,就直接跳转到豆瓣首页了,但其实经历了很多隐藏的过程。
首先接上一步,QQ服务器在判断登录成功后,使页面重定向到之前豆瓣发来的callback并附上code授权码,即 callback=www.douban.com/callback
页面接到重定向,发起 http://www.douban.com/callback 请求
豆瓣服务器收到请求后,做了两件再次与QQ沟通的事,即模拟浏览器发起了两次请求。一个是用拿到的code去换token,另一个就是用拿到的token换取用户信息。最后将用户信息储存起来,返回给浏览器其首页的视图。到此OAuth2.0授权结束。
3、OAuth2.0 专业介绍
OAuth定义了四种角色:
- resource owner(资源所有者)
- resource server(资源服务器)
- client(客户端):代表资源所有者并且经过所有者授权去访问受保护的资源的应用程序
- authorization server(授权服务器):在成功验证资源所有者并获得授权后向客户端发出访问令牌
抽象的OAuth2.0流程如图所示:
- (A) 客户端向资源所有者请求其授权
- (B) 客户端收到资源所有者的授权许可,这个授权许可是一个代表资源所有者授权的凭据
- (C) 客户端向授权服务器请求访问令牌,并出示授权许可
- (D) 授权服务器对客户端身份进行认证,并校验授权许可,如果都是有效的,则发放访问令牌
- (E) 客户端向资源服务器请求受保护的资源,并出示访问令牌
- (F) 资源服务器校验访问令牌,如果令牌有效,则提供服务
一个授权许可是一个凭据,它代表资源所有者对访问受保护资源的一个授权,是客户端用来获取访问令牌的。
授权类型有四种:authorization code, implicit, resource owner password credentials, and client credentials
(1)Authorization Code
授权码是授权服务器用来获取并作为客户端和资源所有者之间的中介。代替直接向资源所有者请求授权,客户端定向资源所有者到一个授权服务器,授权服务器反过来指导资源所有者将授权码返回给客户端。在将授权码返回给客户端之前,授权服务器对资源所有者进行身份验证并获得授权。因为资源所有者只对授权服务器进行身份验证,所以资源所有者的凭据永远不会与客户机共享。
(2) Implicit
隐式授权是为了兼顾到在浏览器中用诸如JavaScript的脚本语言实现的客户端而优化的简化授权代码流程。在隐式授权流程中,不是发给客户端一个授权码,而是直接发给客户端一个访问令牌,而且不会对客户端进行认证。隐式授权提高了一些客户端(比如基于浏览器实现的客户端)的响应能力和效率,因为它减少了获得访问令牌所需的往返次数。
(3) Resource Owner Password Credentials
资源所有者的密码凭据(比如,用户名和密码)可以直接作为授权许可来获取访问令牌。这个凭据只应该用在高度信任的资源所有者和客户端之间(比如,客户端是系统的一部分,或者特许的应用),并且其它授权模式不可用的时候。
(4) Client Credentials
客户端凭据通常用作授权许可
(5) Access Token
访问令牌是用来访问受保护的资源的凭据。一个访问令牌是一个字符串,它代表发给客户端的授权。令牌代表资源所有者授予的对特定范围和访问的时间(PS:令牌是有范围和有效期的),并由资源服务器和授权服务器强制执行。访问令牌可以有不同的格式、结构和使用方法。
(6) Refresh Token
Refresh Token是用于获取Access Token的凭据。刷新令牌是授权服务器发给客户端的,用于在当前访问令牌已经失效或者过期的时候获取新的访问令牌。刷新令牌只用于授权服务器,并且从来不会发给资源所有者。
刷新的流程如图所示:
- (A) 客户端请求获取访问令牌,并向授权服务器提供授权许可
- (B) 授权服务器对客户端身份进行认证,并校验授权许可,如果校验通过,则发放访问令牌和刷新令牌
- (C) 客户端访问受保护的资源,并向资源服务器提供访问令牌
- (D) 资源服务器校验访问令牌,如果校验通过,则提供服务
- (E) 重复(C)和(D)直到访问令牌过期。如果客户端直到访问令牌已经过期,则跳至(G),否则不能继续访问受保护的资源
- (F) 自从访问令牌失效以后,资源服务器返回一个无效的令牌错误
- (G) 客户端请求获取一个新的访问令牌,并提供刷新令牌
- (H) 授权服务器对客户端进行身份认证并校验刷新令牌,如果校验通过,则发放新的访问令牌(并且,可选的发放新的刷新令牌)