标签:
http://oauth.net/2/ 协议的原文。原来是1.0版本,现在是2.0版本了
通俗解释:
http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
要解决的问题:
获取授权。每次登录,都要让用户进行授权。
现实中的例子,只有用户同意授权给妈妈网,腾讯才发放一个令牌给妈妈网,妈妈网凭借这个令牌去腾讯获取用户的信息。
那么就意味着说,令牌的生成规则要跟用户和妈妈网的信息绑定关系。
奇怪,如果这个令牌被泄漏呢?别人也可以凭借这个令牌拿到信息啊。现实生活中,别人即便拿到你的令牌(票券),的确是可以去通行。
但是现实生活中发现了这个漏洞后,会增加一些安排判断,比如车票,别人就算偷到,捡到车票也不能去乘车,还要比对一下是否与身份证号码匹配。
除非你拿到对方的身份证了。这样把安全系数提高。发生的概率就会减少。就算你拿到对方的身份证,有时候还会看看你本人样子是否与身份证照片相差很大。
在我们这一层,你在url中是可以看到key,没错。但是你得同时拿到密钥才行。需要密钥对数据进行签名的。签名失败是不允许访问的。
腾讯的微信是这样子:
1、用户授权后,则生成一个临时性的code返回给客户端
code如何生成的呢?参考了oauth2.0协议
该码与客户端ID和重定向URI,是一一对应关系。
客户端id。重定向的uri,是早就预定义好了。
请求腾讯去获取code的时候,会带两个关键性的参数:腾讯的appid(就是oauth2.0协议中的客户端id)、redirect_uri(腾讯要回跳回来的地址)
现在思考:为什么要验证redirect_uri是否与后台填写的域名一致呢。其实这样可以增加安全性。
我只会重定向到指定的url去。这样会更加安全。不会重定向到攻击者指定的url去。
qq登录的时候,还为了更加安全,做全路径判断了。以前只是同一个域名下即可了。后来为了安全。必须后台填写完全相同的url地址。
比如后台配置必须是这样的完整url: www.abc.com/qqlogin/callback.php
是域名www.abc.com是不行,以前是可以的。
那么会完全验证这个url是否一致。否则就拒绝掉。
这对于passport的参考意义:所有接入passport的子应用,我是不是可以限制回调地址呢?限制在指定域名下就可以。
目前来看,还不需要这样子做。没有遇到问题?
2、凭借appid和临时性的code去获取access_token
3、凭借access_token和用户的openid去获取用户的信息(昵称,头像等等)
通俗例子:
现在想要实现qq登录。
一种办法是:让用户把对方的帐号和密码发给a网站,让a网站去登录qq。那这样就不安全了,因为密码不能泄漏给这些网站。
把帐号和密码直接给a网站,a网站就能获取到qq的所有信息的权力了。这样子不安全。
现在明白原因了,为什么要设计一个用户的access_token,在每个网站不同。就是为了安全性。假设一个用户的access_token在a网站是一样的,在b网站也是一样的。
那么,泄漏了,就麻烦了。因为我可以获取用户的所有资料了。
这个access_token可以理解成令牌。
我在思考,我应该如何设计这种模式呢?
我可以画序列图,这样子清楚解释。
关键是这个access_token,这样子应用就不需要获取用户的密码了。完全通过这个授权层来实现登录。
我觉得code 与access_token是建立了一个映射关系的。
access_token则是与用户的openid建立了映射关系的。
access_token openid(根据appid和qq进行生成)
其实我在返回ticket的时候,完全可以增加一个字段expire,表示过期时间。这样子他们自己可以根据去刷新自己的cookie时长?
子应用和passport系统登录时间不一致,的确会导致一些用户体验不好。
靠近大家的习惯。oauth2.0这样的模式去。
获取临时性的code。然后凭借code获取ticket(类似于access_token)。
每次请求都必须要带上passport授予的key在url中。
思考:qq,微信这些实现oauth2.0登录的时候,为什么除了带上screct还要带上appid呢?
微信登录,只需要带上appid,就可以访问微信了。关于安全性,不过最终都要经过用户的授权:用户的微信帐号必须是登录状态。即便是登录状态,也要经过用户授权访问。
1、跳转到微信的授权登录页面去,不需要screct。因为这个需要用户授权才能操作。不涉及到安全性。之所以要传递一个appid在url中给微信,微信可以知道用户要登录哪个应用而已,方便做提醒"你正在准备登录妈妈网"
2、通过code去获取access_token,需要screct的原因是,这里涉及到安全性了。
为什么要设计一个refresh token?
怕access_token过期。
为什么要增加这个refresh token去延长access_token的有效期呢?
客户端:指的就是第三方应用程序。比如网站。
服务商:如何理解呢?通俗点理解呢。
资源所有者:指用户。这些资源是用户的,比如个人信息,保存的资料都是用户的。
state | 否 | 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 |
这个state指是可以网站自己设置的参数,qq那边只是原封不动的返回来。据说这样可以避免csrf攻击。
不太理解。但是可以模仿。oauth官网文档是推荐填写这个的。既然是为了避免csrf攻击,伪造请求。
那么state的值就不要是一个固定的值了,因为可以伪造。所以要设置成一个动态变化的值。
比如可以:时间戳+随机数。时间戳是可以伪造的(用其他语言生成一个,时间只要同步就可以)。但是加上随机数。就很难确定是哪个随机数了。因为随机数每次都是变化的,对方就算模拟也很难模拟出恰好生成同一个随机数出来,它是在一个范围内变化的。
思考:为什么单独只需要在浏览器重定向(比如腾讯回跳到自己网站)的时候,附加上state返回呢?
其他通过access_token获取用户信息,这些都是服务器之间的通信。很难被截取到。
但是获取临时性code这一步,是在浏览器回跳的时候,别人也可以重定向这个地址,伪造请求。
现在要加上一个每次都变化的值会比较安全点。到底是如何攻击的呢?
passport倒未必需要这样子,我觉得passport调用方是自己的应用。不是外部应用。是自己公司的。是这样的吗?
我现在可以设置一个时间戳,然后缓存在session中。qq会返回过来。如果返回来的值不一样,则提示页面已过期。
这是网页版登录的正式文档:
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&lang=zh_CN
弄错了,结果跑到公众帐号平台去了:
http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html#.E7.AC.AC.E4.B8.80.E6.AD.A5.EF.BC.9A.E7.94.A8.E6.88.B7.E5.90.8C.E6.84.8F.E6.8E.88.E6.9D.83.EF.BC.8C.E8.8E.B7.E5.8F.96code
难怪提示,必须要使用客户端打开。
实际上过程是:二维码。扫描后就可以进行登录了。
我现在想理解一下,这个openid,unionid是根据什么生成的呢?
如何生成的呢?
同一个qq号,每个应用id对应的openid会不同。
容易把人给搞晕:access_token
openid之类的。
根据access_token才能访问。access_token存在有效期。附加上access_token和openid才能拿到指定用户的信息。
目前腾讯分配给我们的appid是一个特殊的appid,由于是特殊性。在腾讯的后台查询不到,腾讯并没有单独提供后台给我们,直接修改回调地址。只能联系对方的技术人员修改
关于当时的背景:理解下面知识点
他们对一个用户(qq)的openid值是根据应用的appid生成的,也就是说:QQ号12348899,换一个appid,这个qq号对应的openid值就不同了。
这样子设计是为了安全考虑。否则不同的应用(比如a公司和b公司的应用),只要知道一个qq号码,就能获取到它的openid去其他地方使用。或者保存到自己的数据库里面。
现在目的要保证不一样,腾讯每个qq的openid值根据应用不同,而不同的。
妈妈网当时为了解决这样的问题:
由于32论坛的域名,都是不一样的一级域名,比如www.gzmama.cn、www.cdmama.cn。根据腾讯的qq机制,那么同一个qq用户在这些应用对应的openid值就不一样了。
想实现32论坛的qq用户,表现得是同一个openid。根据上面对腾讯openid的介绍,腾讯原来的机制无法满足。所以我们当时要求腾讯为我们单独开设了一个appid。
此appid是一个特殊的appid。把很多的应用合在一起。
同意授权,实际上就是根据用户的登录信息和appid生成一个code吗?这个code于这些信息是关联的。
回跳回来的时候,带这个code,凭借这个code可以获取access_token
我以前以为,获取到access_token,获取到code会不安全。但实际上授权的模式已经避免密码泄漏的问题了。
对方如何才能获取到code,code只是一个桥梁,一个中间作用。用完一次就删除了。
关键是对方怎么攻击呢?
我们的目的,就是要避免攻击者去获取用户的资源:照片,资料等信息。
必须通过用户临时授权,每授权一次才能进一步操作。
实际上可以直接返回access_token给客户端。但是不安全。必须要通过code来获取。
要隐藏。在服务器之间进行通信,这样很难抓到包。
我只要拿到access_token,那么也是可以获取用户信息了。
请求的时候带scope参数,这样子授权服务器就知道这个应用打算申请什么权限,这样可以提醒用户:你将要授权进行干嘛,你是否同意。
在oauth2.0协议中,提供了好几种模式。其中一种模式是直接把access_token放到url中返回给客户端了。
标签:
原文地址:http://www.cnblogs.com/wangtao_20/p/4550566.html