简单的背景说明
所谓OAuth2.0就是OAuth这个授权框架的2.0版本,至于1.0已经废弃不用了。
本系列主要讨论OAuth2.0的概念、优缺点、用途以及其使用方法。主要的参考资料是RFC 6749。
如果在此之前你对OAuth2.0知之甚少的话,建议可先尝试一下看看本文,再去读标准文档。我本人在学习OAuth2.0时就有过一段痛苦的经历,在开始学习OAuth2.0这个框架时,我对OAuth一无所知,然后一上来就开始读英文版的RFC标准,结果被里面一大堆初次接触的名词术语搞得晕头转向。幸亏有伟大的互联网帮助,读了一些开源代码再结合前辈们的博文,才把它搞清楚。
如果你已经非常了解OAuth2.0所解决的痛点,那么可以跳过本章,因为对于对OAuth2.0已经有所了解的朋友来说,本章会显得十分啰嗦。
现在各大网站,如微信、微博、淘宝等,都纷纷使用符合OAuth2.0标准的授权机制,如果我们开发的产品与这些软件有交集的话,那么在简单地使用这些公司提供的SDK来开发OAuth2.0的客户端之前,深入地了解一下OAuth2.0,还是很有必要的。
OAuth2.0是用来干什么的
有必要先来了解一下OAuth2.0的用途。
简单地用一句话概括,OAuth2.0是用来给客户端授权的,比如让客户端登录到系统中获得资源。
在一个典型的客户端/服务端(C/S)模型中,客户端需要登录服务端来获取它所需要的资源,比如QQ客户端,它需要先登录到腾讯的服务器后,才能得到好友列表,才能和好友聊天。但如果仅仅是为了登录的话,其实使用OAuth2.0是没有必要的。
OAuth2.0解决了两个问题:
- 单点登录。 象QQ这种既有客户端,又有网页,并且还有其它衍生的业务如QQ空间、腾讯微博、腾讯邮箱等这样的产品,如果每个业务都有一个单独的认证系统,那么要么是用户需要为每个业务记忆一个账号密码,要么后台为了使各个业务能用同一个账号密码登录而需要不停地同步账号信息。使用OAuth2.0时,只需要在授权服务上保存用户信息,其它业务服务不需要保留用户信息。如何实现?后面会展开讨论。当然,单点登录并非OAuth2.0所要解决的主要问题,可替代的方案还是较多的。
- 第三方授权的安全问题。 OAuth2.0可以让第三方应用在得到授权时,不需要知道用户的账号密码。比如你需要开发一个产品,在这个产品中,需要具有微信分享功能,可以将一些内容分享给自己的微信好友。在分享之前,当然首先需要使用用户的微信账号登录,那么问题来了,用户在你的应用中输入他的微信账号与密码,你分秒就可以通过你的应用盗用他的账号,而一旦他的账号被盗用,他账号下的所有资源都将全部暴露,而盗用者只要修改了密码,以及手机邮箱等其它信息,用户将永远找不回这个账号。这是OAuth2.0所要解决的主要问题,如何解决?继续卖个关子,后面讨论。
另外,在实践过程中,我还发现使用OAuth2.0所带来的意外红利,比如说WEB网站前后端分离时鉴权可以更便利,以及解决使用cookie所带来的由于本地信息被泄露所导致的账号被盗问题。这些将单独写一章来讨论。
当然,OAuth2.0并不能解决所有问题,它只不过在安全性、开放性、便利性中找到了一个较佳的平衡点,老生常谈的“凡事有利必有弊”这句话在这里同样适用。关于这一点,也将在后面展开讨论。
先来讲个故事
在讲OAuth2.0那些流程、名词、术语前,先来讲个故事吧。
请看上面这张图,左边这部分是客户端/服务端模型,右边这部分是张三与银行。客户端从服务端获取资源的过程,可以类比于张三从银行取钱的过程,这里银行是服务端,张三是客户端,银行卡是账号,密码是记在张三脑子里的银行卡密码。在简单的应用中,这样的关系已经足够了,张三需要用钱的时候,拿着卡跑到银行中取钱,然后再去付钱买东西。
这样的模型在某些情况下并不方便,请看下面这张图:
当张三在三个银行都有账号时,他需要持有三张银行卡,分别记住每张银行卡的密码。当然你可以为这些银行卡都设置相同的密码,但卡号总不能相同吧,结果,张三不得不在皮夹里塞上三张卡。随着张三的银行卡越来越多,皮夹也越来越满,终于有一天,张三不乐意了,强烈要求这些银行能只用一张卡,就可以在各个银行中存钱取钱,以及在餐厅超市中刷卡消费,同时李四、王五等等也纷纷响应。经过漫长卓越的努力,银行的大佬们终于决定坐在一起讨论如何来解决这个问题了。又过了几十年,终于有了一卡通。这下,张三只需要带一张卡啦。
然而,这仅仅也只是实现了用一个账号,在多个业务中登录的功能。而且请注意,张三虽然只需要带一张卡,但是在每次取钱或消费时,还是必须刷卡并输入密码。有没有办法不用每次都刷卡输密码呢?有!
有一天,万能的马云大神给张三带来了支付宝。
从此以后,张三吃快餐、买奶粉再也不用刷卡输密码了,只要亮一下二维码。
觉得不安全了是吧。张三也是这么认为的,万一手机丢了怎么办?万一二维码给人家拍走了怎么办?OAuth2.0也有同样类似的问题,并有相应的解决方案或说法,后面会专门讨论。前面我也提到过,OAuth2.0只是在安全性、开放性、便利性中找到了一个较佳的平衡点,没有一个方案是万能的。如果要安全,那最好是在超市刷卡输密码付钱时,还必须插个U盾,这显然不会是我们要的东西。
好了,至此,生活已经变得很美好了。然而生命不息,奋斗不止。到目前为止,我们看到,不管是用多张卡还是用一张卡,不管是用卡还是用二维码,使用的主体都是张三他自己,没有其它人。
现在,张三的儿子要上大学了,每个月需要生活费。张三当然不能把自己的卡直接交给儿子去用,即便是高中里再乖的孩子,到了大学也难保不学会乱花钱不是?于是通常的做法是张三到银行给儿子办一张卡,然后每个月从自己的账户里打钱过去。看上去这也挺好。但是这样一来,张三他们花了几十年才得到的一卡通便利又没了,张三又得在两张卡上开始折腾,然后张三的女儿也要上大学了......
好在银行还有一个叫做副卡的东西,张三在自己的账户下申请了一张副卡,然后设定其每月的限额,交给儿子去用。儿子拿了这张卡,绑定到自己的支付宝上。女儿上大学后也是这么做。
于是张三所要操心的就只是赚更多的钱了。
故事到这里就该结束了,在后面的章节中我会将这个故事与OAuth2.0结合起来描述,OAuth2.0大抵就是处理了这类问题。但是这个故事应该还会延续,因为OAuth2.0并不完美,后面还有很多路要走,我们拭目以待。