vlambda博客
学习文章列表

一图搞定Oauth2.0授权码模式

    本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式

    非常简单的一件事情,网上一堆神乎其神的讲解,让我不得不写一篇文章来终结它们。

    一项新的技术,无非就是了解它是什么,为什么,怎么用。但首先在读本文之前,你要先对OAuth2.0有一定的了解,建议先读一下阮一峰的oauth2.0文章,带着疑问再来读本文效果更好。

http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html


Oauht2.0授权码模式--概念篇 


下面切入正题重点讲一下oauth2.0中的授权码模式:

授权码模式(Authorization code)流程

    授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。

还是以有道云笔记使用QQ账号登录为例进行讲解:

1、在有道云官网点击使用qq登录

2、跳转到qq登录页面输入用户名密码,然后点授权并登录

一图搞定Oauth2.0授权码模式3、跳回到有道云笔记页面,成功登录

一图搞定Oauth2.0授权码模式

这几秒钟之内发生的事情,在无知的用户视角看来,就是在有道云官网上点击了qq授权就登录成功了。在一些细心的用户视角看来,页面经历了从有道qq,再从qq有道的两次页面跳转。

但作为一个专业的安全从业人员,我们还应该从上帝视角来看这个过程。


2、Oauth2.0授权码模式--上帝视角   


  简单来说,上述例子中的有道云笔记就是客户端,QQ就是认证服务器,OAuth2.0就是客户端和认证服务器之间由于相互不信任而产生的一个授权协议。呵呵,要是相互信任那QQ直接把自己数据库给有道好了,你直接在有道输入qq账号密码查下数据库验证就登陆呗,还跳来跳去的多麻烦。

    先上一张图,该图描绘了只几秒钟发生的所有事情用上帝视角来看的流程。

一图搞定Oauth2.0授权码模式    就这这张图,来说一下上述例子中的三个步骤在图中的表现。所用到的请求路径名称都是虚构的,所附带的请求参数忽略了一些非重点的。


Oauth2.0授权码模式--实现过程  

 第一部分——使用QQ进行第三方授权


一图搞定Oauth2.0授权码模式

     <1>用户在有道云官网单击“使用qq账号登录”,实际上是向有道云的服务器发起了一个 http://www.youdaoyun.com/leadToAuthorize 的请求。

一图搞定Oauth2.0授权码模式

https://graph.qq.com/oauth2.0/authorize

?client_id=100255473

&response_type=code

&redirect_uri=https://note.youdao.com/login/acc/callback

&state=qZhHgy6Leu0QFhHeFhMqy0ZZZZZZKMPK0

    其中:

response_type=code:此参数和参数值用于提示授权服务器当前客户端正在进行授权码授权流程,要求返回授权码。

client_id:客户端身份标识(本例中为有道云笔记身份标识),让QQ知道是谁在请求。

scope:指定客户端请求的访问范围。

state:由客户端服务器生成的随机字符串,后续用户进行授权客户端的请求时也会携带此字符串用于比较,这是为了防止CSRF攻击。


第二部分--跳转到qq登录页面输入用户名密码或扫码登录进行授权


一图搞定Oauth2.0授权码模式

一图搞定Oauth2.0授权码模式

一图搞定Oauth2.0授权码模式

一图搞定Oauth2.0授权码模式

https://note.youdao.com/login/acc/callback?

code=282CA5A02CC5953158E61FCB61B06FE8

&state=qZhHgy6Leu0QFhHeFhMqy0ZZZZZZKMPK0

    其中:

●state:该值将与有道服务端在请求中最初设置的值相同。有道后台将检查重定向中的状态值是否与最初设置的状态值相匹配。这可以防止CSRF和其他相关攻击。

●code:是授权服务器生成的authorization code值。code相对较短,通常持续1到10分钟,具体取决于授权服务器设置。

一图搞定Oauth2.0授权码模式


第三部分--跳回有道云笔记页面,成功登录


这一步背后的过程其实是最繁琐的,但对于用户来说是完全感知不到的。用户在QQ登录页面点击授权登陆后,就直接跳转到有道云首页了,但其实经历了很多隐藏的过程。

有道服务器收到请求后,做了两件再次与QQ沟通的事,即模拟浏览器发起了两次请求。一个是用拿到的code去换token,另一个就是用拿到的token换取用户信息。最后将用户信息储存起来,返回给浏览器其首页的视图。到此OAuth2.0授权结束。一图搞定Oauth2.0授权码模式

<5>现在客户端已经拥有了服务器派发的授权码Authorization code,接下来便可以使用Authorization code和其他参数向服务器请求Access Token(POST方式)。   

https://b.com/oauth/token?

client_id=CLIENT_ID

&client_secret=CLIENT_SECRET

&grant_type=authorization_code

&code=AUTHORIZATION_CODE

& redirect_uri=CALLBACK_URL

    其中:

●grant_type=authorization_code :告知服务器当前第三方应用使用Authorization Code授权流程。

●code :上一步拿到的授权码。

●redirect_uri :与请求authorization code时使用的redirect_uri相同。某些资源(API)不需要此参数。

●client_id :客户端标识。

●client_secret :客户端密钥。这确保了获取access _token的请求只能从服务端发出。

<6>QQ认证服务器将会验证步骤<5>中的请求参数,当验证通过后(校验Authorization code是否过期,client idclient secret是否匹配等),服务器将向有道云服务端返回Access_token

具体做法是向redirect_uri指定的网址,发送一段 JSON 数据。

{    

  "access_token":"ACCESS_TOKEN",

  "token_type":"bearer",

  "expires_in":2592000,

  "refresh_token":"REFRESH_TOKEN",

  "scope":"read",

  "uid":100101,

  "info":{...}}

实例:

{

  "access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",

  "token_type":"bearer",

  "expires_in":3600,

  "refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",

  "scope":"create delete"

}

有道云服务器收到access_token请求后,用拿到的token换取用户信息。最后将用户信息储存起来,返回给浏览器其首页的视图。到此OAuth2.0授权结束。直到access_token 过期或失效之前,客户端可以通过资源服务器API访问用户的帐户,并具备scope中给定的操作权限。

一图搞定Oauth2.0授权码模式