现在越来越多的网站开放api了,而且大部分都用了OAuth的认证方式,对于没接触过OAuth的人来说一开始理解起来感觉很困惑,觉得这个东西很麻烦,这篇文章就简单的从什么是OAuth,为什么要有OAuth,OAuth的认证流程,以及OAuth为什么要这样设计来谈一下。但是鉴于现在OAuth都已经有2.0了,但是2.0却不兼容1.0,而2.0主要依赖的是https,所以这里还是主要是来讲OAuth1.0的,确切的说是OAuth1.0a的。
什么是OAuth
当你进入OAuth的官网,就能看到那句最醒目的描述
An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.
OAuth是一种开放的并且简单安全的协议,能够让你可以对桌面程序和web程序进行授权。好吧,看上去还是很抽象,那就接着看吧。
为什么要用OAuth
一个非常常见的需求,就是我想获得用户在其他网站上的数据,比如,我做了个相片集中展示的网站,我希望用户可以导入他在flickr,或者facebook,或者人人上的照片。而OAuth就是一种能够安全方便的让我可以去别的网站获得用户的数据。
ok,你可能会想这个事情不简单嘛,我直接把我在其他网站的用户名密码告诉这个网站不就可以了。于是问题来了,这个网站你信的过吗,把用户名密码告诉他干坏事肿么办,如果我哪天不想用这个网站了,也不想让这个网站再获取数据了我是不是要改密码呢。
他真的没有存储我的密码吗,CSDN都明文了,我还能相信爱情吗╮( ̄▽ ̄”)╭ 于是OAuth就是为了解决这些授权问题应运而生的。
OAuth最终会为每一个用户的每一个授权的应用都生成一对access token和access token secret,可以把它当做访问用户数据的特殊的用户名和密码。由于对于每一个用户而言,每一个授权应用的token和secret都是不同的,所以用户可以很方便的收回某个应用的授权而不影响其他的应用,而且不用去改密码,而且如果用户更改了密码,那些授权的token和secret依旧不受影响,这就是OAuth的解决方案了。
那么应用如何去获得token和secret就是下面要讲的了。
OAuth的认证流程
首先奉上一张官网上的流程图
首先要明白整个需要三个角色,user,consumer,provider,首先consumer就是我要做的网站或者是说给用户提供服务的应用,user很明显就是用户了,provider就是consumer想要获取数据的地方。然后我们整个过程其实就是分三步来的。
- consumer首先向provider申请,去获得request token
- consumer吧用户重定向到provider的网站去授权request token
- consumer通过授权了的request token去向provider获得access token
由图可以看到左边是流程,右边是每次携带的数据,每次都需要用密钥对数据进行url encode之后HMAC-SHA1签名的,然后oauth_nonce是一个随机的32位字符串和timestamp时间戳配合用来防止重放攻击的。
在应用创建的时候也就是很久很久以前。。。consumer需要先向provider申请consumer key和consumer secret,这个是每个应用一个,与用户无关的,第一步申请request token的时候就需要用consumer secret来签名。然后provider会返回request token和request token secret。
第二步就需要用consumer secret和request token secret来加密,重定向到provider用户的网站去让user授权request token,还记得OAuth定义吗,OAuth不仅可以为web应用授权,也可以为桌面应用授权,于是在这一步两种应用会稍有不同,如果是web应用,那么web会提供一个callback,回调地址,provider就可以通过这个地址,把一个vertify code传给consumer,而桌面应用需要用户手动把这个值输入给应用。
最后通过vertify code这个值和request token向provider申请就会获得access token和access token secret了,之后应用通过access token就可以在provider那里获得用户的数据了。
ok,其实作为开发者是没有必要对于整个过程亲自去构造的,OAuth是开源的协议,然后官方也提供了各种语言的包在这里。
OAuth为什么要这样设计
对于OAuth过程有些繁琐啊,需要三步才可以,那么我们能不能简化这个过程呢?
我们考虑如果我们只用一步就是consumer直接向provider去要access token,这显然是不行的,就是这样的话consumer根本不知道去要谁的access token,那么如果用户自己生成一对access token输入给consumer呢,也不行,用户不知道或者说会忘记这个access token是给谁了。再或者consumer把用户重定向到provider的网站,然后直接返回access token不行吗,不行的,别忘了我们还有客户端应用的,为了避免用户输入一大长传的access token还是需要两步的,也就是说我们至少需要两步。
那么我们能不能用两步呢,就是先把用户重定向到provider的网站,然后,consumer再来获取access token不行吗。恩,这个事情涉及到最早的1.0版本的问题,感谢这篇文章以及文章作者的解答,因为在1.0版本是没有vertify code的,然后再注意stackoverflow上这个问题的解答也就是说以前是让用户输入request token的,所以需要这个东西设计的简短才行,于是便有现在的双token,来最终获取access token的方案。
1.0a的改变
最后我们来谈谈为什么从最初的1.0变到现在1.0a的呢,答案很简单,就是有严重的安全漏洞!这篇文章有详细的说明,这里我简单说一下。
首先攻击者去访问consumer的网站,然后consumer就去向provider申请request token,之后把攻击者重定向到provider的网站,ok攻击者不去自己授权,而是把这个地址保存下来,之后利用诱骗啊想办法让受害者去点击这个地址,然后受害者进行授权,之后会调用回调地址,而这个回调地址是很容易构造的,于是攻击者就去自己调用回调地址给consumer,这样consumer就会获取到受害者的access token了,这样攻击者就可以利用consumer的网站来获取受害者的数据了。
于是1.0a就是修复了这个问题,加入了vertify code,并且对于callback也有一些限制。
写在最后
如果你对1.0或者2.0的流程有兴趣的话,可以来看这篇文章,然后对于2.0似乎还有颇多争议啊OAuth 2.0对Web有害吗?
图片有意思。。
这篇文章写的实在是寓教于乐啊,希望博主以后多写此类文章。