oauth初步学习小结
还记得开心网,人人网这些SNS刚出来时,它们中有的功能,比如是要导入GOOGLE,MSN的联系人列表,这个时候要我们输入自己在这些系统上的帐号和密码,之后借助API或者WEBSERVICE等去把这些网站上的属于自己的资源导入到自己的网站中,但是,其实这个是很危险的!因为很有可能这些网站已经获得了你的个人私隐信息了,尽管他们作了承诺,现在,我们可以用oauth协议去初步解决这个三方之间的不信任问题了(用户,第三方应用,服务提供商)。
由于最近在学习sina的微博API,因此小结一下。
一 什么是oauth
在官方网站的首页,可以看到下面这段简介:
An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.
大概意思是说OAUTH是一种开放的协议,为桌面程序或者基于BS的web应用提供了一种简单的,标准的方式去访问需要用户授权的API服务。OAUTH类似于Flickr Auth、Google's AuthSub、Yahoo's BBAuth、 Facebook Auth等。OAUTH认证授权具有以下特点:
1. 简单:不管是OAUTH服务提供者还是应用开发者,都很容易于理解与使用;
2. 安全:没有涉及到用户密钥等信息,更安全更灵活;
3. 开放:任何服务提供商都可以实现OAUTH,任何软件开发商都可以使用OAUTH;
OAuth开始于2006年11月,当时布莱恩·库克(Blaine Cook)正在开发 Twitter的OpenID实现。与此同时,Ma.gnolia需要一个解决方案允许使用OpenID的成员授权Dashboard访问他们的服务。这样库克, 克里斯·梅西纳(Chris Messina)和来自 Ma.gnolia的拉里·哈尔夫(Larry Halff)与戴维·雷科尔顿(David Recordon)会面讨论在Twitter和Ma.gnolia API上使用OpenID进行委托授权。 他们讨论得出没有开发标准完成API访问的委托。
2007年4月,成立了OAuth讨论组,这个由实现者组成的小组撰写了一个开放协议的提议草案。来自Google的德维特·克林顿(DeWitt Clinton)获悉OAuth项目后,表示他有兴趣支持这个工作。2007年7月,团队起草了最初的规范。随后,Eran Hammer-Lahav加入团队并协调了许多OAuth的稿件,创建了更为正式的规范。2007年10月3日, OAuth核心 1.0最后的草案发布了。
2010年4月,OAuth 1.0协议发表为RFC 5849,一个非正式RFC。
二 oauth的产生背景
oauth的产生目的其实就是为了解决其三方不信任的问题的,比如上面举例中的例子,
三方是:google(或者MSN)这个叫服务资源提供方,用户,第三方应用(比如SNS),
有了oauth,则如果用户在使用SNS过程中,需要用到服务提供方上的资源(比如帐号,密码等),则不需要再第三方中存储或暴露个人私人信息的。
三 oauth的组成和术语定义
一个典型的OAuth应用通常包括三种角色,分别是:
Consumer:消费方
Service Provider:服务提供者
User:用户
用户好理解,不必多言,消费方和服务提供者则需要解释一下,举例来说:假设我们做了一个SNS,它有一个功能,可以让会员把他们在Google上的联系人导入到SNS上,那么此时的消费方就是SNS,而服务提供者则是Google。
再来看一个图:
如图 所示 OAuth 解决方案中用户、消费方及其服务提供方之间的三角关系:当用户需要 Consumer 为其提供某种服务时,该服务涉及到需要从服务提供方那里获取该用户的保护资源。OAuth 保证:只有在用户显式授权的情况下(步骤 4),消费方才可以获取该用户的资源,并用来服务于该用户。
从宏观层次来看,OAuth 按以下方式工作:
消费方与不同的服务提供方建立了关系。
消费方共享一个密码短语或者是公钥给服务提供方,服务提供方使用该公钥来确认消费方的身份。
消费方根据服务提供方将用户重定向到登录页面。
该用户登录后告诉服务提供方该消费方访问他的保护资源是没问题的。
oauth的术语:
了解一下 OAuth 协议的一些基本术语定义:
Consumer Key:消费方对于服务提供方的身份唯一标识。
Consumer Secret:用来确认消费方对于 Consumer Key 的拥有关系。
Request Token:获得用户授权的请求令牌,用于交换 Access Token。
Access Token:用于获得用户在服务提供方的受保护资源。
Token Secret:用来确认消费方对于令牌(Request Token 和 Access Token)的拥有关系。
OAUTH相关的三个URL:
Request Token URL: 获取未授权的Request Token服务地址;
User Authorization URL: 获取用户授权的Request Token服务地址;
Access Token URL: 用授权的Request Token换取Access Token的服务地址;
OAUTH相关的参数定义:
oauth_consumer_key: 使用者的ID,OAUTH服务的直接使用者是开发者开发出来的应用。所以该参数值的获取一般是要去OAUTH服务提供商处注册一个应用,再获取该应用的oauth_consumer_key。如Yahoo该值的注册地址为:https://developer.yahoo.com/dashboard/
oauth_consumer_secret:oauth_consumer_key对应的密钥。
oauth_signature_method: 请求串的签名方法,应用每次向OAUTH三个服务地址发送请求时,必须对请求进行签名。签名的方法有:HMAC-SHA1、RSA-SHA1与PLAINTEXT等三种。
oauth_signature: 用上面的签名方法对请求的签名。
oauth_timestamp: 发起请求的时间戳,其值是距1970 00:00:00 GMT的秒数,必须是大于0的整数。本次请求的时间戳必须大于或者等于上次的时间戳。
oauth_nonce: 随机生成的字符串,用于防止请求的重放,防止外界的非法攻击。
oauth_version: OAUTH的版本号,可选,其值必须为1.0。
OAUTH HTTP响应代码:
HTTP 400 Bad Request 请求错误
Unsupported parameter 参数错误
Unsupported signature method 签名方法错误
Missing required parameter 参数丢失
Duplicated OAuth Protocol Parameter 参数重复
HTTP 401 Unauthorized 未授权
Invalid Consumer Key 非法key
Invalid / expired Token 失效或者非法的token
Invalid signature 签名非法
Invalid / used nonce 非法的nonce
简单的来说,OAUTH认证授权就三个步骤,三句话可以概括:
1. 获取未授权的Request Token
2. 获取用户授权的Request Token
3. 用授权的Request Token换取Access Token
流程图如下:
具体每步执行信息如下:
A. 使用者(第三方软件)向OAUTH服务提供商请求未授权的Request Token。向Request Token URL发起请求,请求需要带上的参数见上图。
B. OAUTH服务提供商同意使用者的请求,并向其颁发未经用户授权的oauth_token与对应的oauth_token_secret,并返回给使用者。
C. 使用者向OAUTH服务提供商请求用户授权的Request Token。向User Authorization URL发起请求,请求带上上步拿到的未授权的token与其密钥。
D. OAUTH服务提供商将引导用户授权。该过程可能会提示用户,你想将哪些受保护的资源授权给该应用。此步可能会返回授权的Request Token也可能不返回。如Yahoo OAUTH就不会返回任何信息给使用者。
E. Request Token 授权后,使用者将向Access Token URL发起请求,将上步授权的Request Token换取成Access Token。请求的参数见上图,这个比第一步A多了一个参数就是Request Token。
F. OAUTH服务提供商同意使用者的请求,并向其颁发Access Token与对应的密钥,并返回给使用者。
G. 使用者以后就可以使用上步返回的Access Token访问用户授权的资源。
基本就是用Request Token换取Access Token的过程。这里需要注意的是,对服务提供者而言,Request Token和Access Token的生命周期不一样,通常,Request Token的生命周期很短,一般在一个小时以内,这样相对安全一些;而Access Token的生命周期很长,往往是无限,如此一来,消费方就可以把它保存起来,以后的操作就无需用户再授权了,即便用户修改账号密码,也不会受影响,当然,用户可以废除消费方的授权。
四 再用通俗点的语言去说这个流程吧
网上的说明还是比较复杂,我再简化下。
1) 服务商:google
2) 第三方:SNS
3) 用户
步骤为:
1) 第三方先要去GOOGLE注册好cosumer_key和consumer_secret,
2) SNS向GOOGLE发起请求,对GOOGLE说:HI,你看,我用你给的cosumer_key和consumer_secret来请求你了,我是再你这里申请的哦
3) GOOGLE对SNS说:好,我认得你了,我返回给你一个未经过用户授权的oauth_token和oauth_token_secet吧(有的文中也叫Request Token 和及其相对应的 Token Secret)
4) 当用户要使用SNS时,假如要调用到GOOGLE的服务时,则SNS引导用户到GOOGLE的网站,这个时候,SNS是把oauth_token带上了,这个时候,一般会让用户在网站
GOOGLE上用帐号密码先登陆一次,当登陆完毕后,GOOGLE询问是否授权SNS访问用户自己的信息
5) 用户如果允许SNS访问自己的授权信息,则GOOGLE通过 URL 引导用户重新回到SNS那里,这个时候,SNS再用用户授权过的request token,又向GOOGLE去请求一个ACCESS TOKEN。
6) GOOGLE返回ACCESS TOKEN给SNS,那么SNS就可以开始访问GOOGLE的资源了。
五 OAuth和OpenID的区别
OAuth关注的是authorization;而OpenID侧重的是authentication。从表面上看,这两个英文单词很容易混淆,但实际上,它们的含义有本质的区别:
authorization: n. 授权,认可;批准,委任
authentication: n. 证明;鉴定;证实
OAuth关注的是授权,即:“用户能做什么”;而OpenID关注的是证明,即:“用户是谁”。
如果混淆了OAuth和OpenID的含义,后果很严重。以国内某网站开发的应用为例:它的功能是通过OAuth授权让新浪微博和豆瓣的用户使用各自的身份发表评论,此类应用属于身份证明问题,本应该通过OpenID来实现,但因为错误的使用了OAuth,从而带来安全隐患:设想一下用户只是在网站上发表了评论而已,但却赋予了网站随意操作自己私有数据的权利
六 OAuth安全机制是如何实现的?
OAuth 使用的签名加密方法有 HMAC-SHA1,RSA-SHA1 (可以自定义)。拿 HMAC-SHA1 来说吧,HMAC-SHA1这种加密码方法,可以使用 私钥 来加密 要在网络上传输的数据,而这个私钥只有 Consumer及服务提供商知道,试图攻击的人即使得到传输在网络上的字符串,没有 私钥 也是白搭。
私钥是:consumer secret&token secret (哈两个密码加一起)
要加密的字符串是:除 oauth_signature 外的其它要传输的数据。按参数名字符排列,如果一样,则按 内容排。如:domain=kejibo.com&oauth_consumer_key=XYZ&word=welcome......................
前面提的加密里面都是固定的字符串,那么攻击者岂不是直接可以偷取使用吗?
不,oauth_timestamp,oauth_nonce。这两个是变化的。而且服务器会验证一个 nonce(混淆码)是否已经被使用。
那么这样攻击者就无法自已生成 签名,或者偷你的签名来使用了。
七 参考资料
本文摘录了如下优秀文的参考资料
http://kejibo.com/oauth/
http://www.douban.com/service/apidoc/auth#认证流程及访问资源流程
http://www.ibm.com/developerworks/cn/java/j-lo-oauth/index.html
http://www.skiyo.cn/2010/08/11/understanding-oauth-and-douban-oauth-test/#more-404
http://huoding.com/2010/10/10/8
http://blog.csdn.net/hereweare2009/archive/2009/03/08/3968582.aspx