oauth授权协议的原理

http://oauth.net/2/ 协议的原文。原来是1.0版本,现在是2.0版本了

https://ruby-china.org/topics/15396

https://blog.yorkxin.org/posts/2013/09/30/oauth2-1-introduction/

通俗解释:

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中返回给客户端了。这种是简化模式。存在token被泄漏的风险。

        "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600,
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
       "example_parameter":"example_value"

要有访问令牌access_token。访问令牌有个过期时间。如果要延长,就要使用refresh_token来进行刷新。

access_token有效期是2个小时。refresh_token有效期是30天。

在qq中,Access_Token的有效期默认是3个月,过期后需要用户重新授权才能获得新的Access_Token。

这是php版本的 演示:http://brentertainment.com/oauth2/lockdin/authorize?response_type=code&client_id=demoapp&redirect_uri=http%3A%2F%2Fbrentertainment.com%2Foauth2%2Fclient%2Freceive_authcode&state=6507ae4073f82d4a228eeef1a5af22d6#

https://github.com/bshaffer/oauth2-demo-php  这是官方提供的各个语言的demo

access_token与openid有什么区别呢?完成的意义有什么不一样呢?

在oautho2.0协议原文中,只有access_token,并没有openid的概念。所以openid只是在此基础上加的一个概念。

延长令牌,实际上是重新生成一个令牌:       重新生成refresh_token和access_token,先判断这个refresh_token是不是合法就行了。

access_token和openid都要实时生成。

使用一种算法来生成。这种算法必须是可逆的。也就是根据access_token能够反解出uid出来。openid的值也是要一样的。

使用一个密钥来生成。

desc算法吗?

这篇文章比较好讲述了openid和access_token的区别

http://desert3.iteye.com/blog/1701626

关于access_token被盗用的问题思考

想想现实生活中的例子,如果你捡到别人的火车票后,直接可以去乘车,以前是没有身份认证。我只认车票就放行。

这个动作就类似于,拿了access_token。

现在我们的思路与车票增加验证是一样的思路,是增加验证,把门槛提高。

具体这样做:你拿到access_token还不够。还需要传递密钥来验证才行。

就算你能偷到access_token还不够,你还得知道密钥才行。

现在明白access_token的有效期不是安全的关键因素。短一点的确是比长更加安全。

安全的核心因素是什么呢?就是增加障碍物,门槛增加。

考虑到用code交换access_token是服务器之间的交互。code是容易被知道,但是密钥很难知道。token交换的时候是服务器之间的通信了。

总结:思路就是增加多几道的验证门槛。

access_token准确的理解应该是这样:

是用户对第三方应用进行授权,授权可以在第三方应用进行登录。比如妈妈网的用户,可以在挂号网站进行登录。这需要用户进行授权才行。

授权过的用户会生成一个access_token,这个access_token要与应用id和用户id进行关联(对应关系存储起来)

这句话理解到了本质;OAuth可以把提供的Token,限制在一个网站特定时间段的的特定资源。

为什么通过access_token就能直接去获取用户的信息呢?根本不需要传递密钥去。

腾讯和微博在这方面是一样的模式。怎么来理解呢?难道是基于这样一个假设:access_token不能随便被拿到。需要门槛。所以如果你能够拿到,那就说明你是正常的用户。实际上,我觉得如果是这样的理解,这种理解就是不够全面的。

把client_id和client_secret看成就是这个app访问授权中心的帐号和密码,这么来理解会更加通俗点

这里解释了,为什么access_token不要时间太长。

短期token和长效的身份凭据 - 原先的OAuth,会发行一个 有效期非常长的token(典型的是一年有效期或者无有效期限制),在OAuth 2.0中,server将发行一个短有效期的access token和长生命期的refresh token。这将允许客户端无需用户再次操作而获取一个新的access token,并且也限制了access token的有效期。 

通俗点说,access_token是故意设置比较短的时间。然后增加一个拥有长有效期的refresh_token,来延长access_token的。

access_token的生成方式?

最好是不要在 token 字串附上这些信息,即使是 hash 过的也不好,因为这样子就有机会可以假造 token 。要把 token 字串视为一个参照,服务器用这个 token 字串去查到真正的授权内容。也就是说,access_token从安全角度来说,还是要用数据进行存储的。

Access Token 是一個字串,記載了特定的存取範圍 (scope) 、時效等等的資訊。



两次的access_token:

8576C24EEA96E6AC8B035C375A47C922

8576C24EEA96E6AC8B035C375A47C922

两次的刷新token:

5FC5A99DA4774E7E3569B8BDC1170138

5FC5A99DA4774E7E3569B8BDC1170138

B03CD9A2AF5BA4CDCEA541366EFF995E

52C78B6D6F1D10979B1ED46B5F8709A2

每一次一个code。

通过openid获取用户信息的接口思考

想要获取用户的资料,通过传递openid来获取。但是还不够。如果知道openid被泄漏了。那么就可以获取用户资料,不安全了。

所以还要增加一个门槛,要传递一个access_token。先验证access_token的合法性。access_token带有失效期。是与client_id和user_id关联了。如果access_token合法,就能查询到对应的client_id和user_id的信息。那么user_id知道了就方便查询哪个用户信息了。并且,我们还要验证openid的合法性。openid是根据user_id和client_id换成一定算法生成出来的。所以查询出的client_id和user_id,就能用算法算出openid,假设是openid_b,与传递过来的openid_a对比,是否一致。

不一致,就要报错:openid错误。

总共两个错误:access_token错误和openid错误。



思考:

发现要研究,就把一些东西给研究透彻。然后自己能够回答一些关键性的疑惑。抛出一些问题来,才能解释掉。

比如oauth,不用输入帐号和密码就可以了。

以为有个access_token就可以。

那岂不是没输入帐号和密码就能拿到access_token。
时间: 2024-08-10 23:16:35

oauth授权协议的原理的相关文章

OAuth 授权过程工作原理讲解

转自:http://www.imooc.com/article/10931 在一个单位中,可能是存在多个不同的应用,比如学校会有财务的系统会有学生工作的系统,还有图书馆的系统等等,如果每个系统都用独立的账号认证体系,会给用户带来很大困扰,也给管理带来很大不便.所以需要设计一种统一登录的解决方案.比如我登陆了百度账号,进贴吧时发现已经登录了,进糯米发现也自动登录了.常见的有两种情况,一种是SSO(单点登录)效果是一次输入密码多个网站可以识别在线状态:还有一种是多平台登录,效果是可以用一个账号(比如

(转)OAuth 2.0授权协议详解和流程

这篇文章主要介绍了OAuth 2.0授权协议详解,本文对OAuth协议做了详解讲解,对OAuth协议的各个方面做了分解,读完本文你就会知道到底啥是OAuth了,需要的朋友可以参考下 OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版.本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749. 一.应用场景 为了理解OAuth的适用场合,让我举一个假设的例子.有一个"云冲印"的网站,可

什么是OAuth授权?

什么是OAuth授权? 一.什么是OAuth协议 OAuth(开放授权)是一个开放标准. 允许第三方网站在用户授权的前提下访问在用户在服务商那里存储的各种信息. 而这种授权无需将用户提供用户名和密码提供给该第三方网站. OAuth允许用户提供一个令牌给第三方网站,一个令牌对应一个特定的第三方网站,同时该令牌只能在特定的时间内访问特定的资源. 二.OAuth的原理和授权流程 OAuth的认证和授权的过程中涉及的三方包括: 服务商:用户使用服务的提供方,一般用来存消息.储照片.视频.联系人.文件等(

OAuth授权过程

什么是OAuth授权? 一.什么是OAuth协议 OAuth(开放授权)是一个开放标准,所谓OAuth(即Open Authorization,开放授权),它是为用户资源授权提供了一种安全简单的标准, 允许第三方网站在用户授权的前提下访问在用户在服务商那里存储的各种信息. 而这种授权无需将用户提供用户名和密码提供给该第三方网站而是直接从服务商提供的页面直接登录. OAuth允许用户提供一个访问标记(专业点叫做令牌)给第三方网站,一个访问标记(专业点叫做令牌)对应一个特定的第三方网站,同时该访问标

经验之谈—OAuth授权流程图

事实上我们在开发中,常常须要解决获得用户的一些特定的数据,比方:能够选择使用微博登陆.使用QQ登陆等等.然后我们间接的获得用户的头像.昵称等信息.这些都涉及到OAuth授权的内容 OAuth授权有这么几个特点: OAuth 协议为用户资源的授权提供了一个安全的.开放而又简易的标准 OAuth 的授权不会使第三方触及到用户的帐号信息 OAuth 同意用户提供一个令牌.而不是username和password来訪问他们存放在特定服务提供者的数据 每个令牌授权一个 特定的站点 在 特定的时段内 訪问

[iOS微博项目 - 2.0] - OAuth授权3步

A.概念 OAUTH协议为用户资源的授权提供了一个安全的.开放而又简易的标准.与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH是安全的.oAuth是Open Authorization的简写. B.使用3步骤 OAUTH认证授权就三个步骤,三句话可以概括: 1. 获取未授权的Request Token 2. 获取用户授权的Request Token 3. 用授权的Requ

OAuth授权相关

OAuth协议是用于授权的开放标准.目前有两个版本1.0与2.0,后一个版本并不兼容前面的版本,而是考虑了客户端程序开发的简洁性. 授权的参与者有三方,一般称作Service Provider, Consumer, User.通常的情形是,User想访问Consumer的资源,而又对其不信任,可以用信任方Service Provider的用户名与密码登录.比如有用户想通过微博账号使用cnblogs,微博是Service Provider,cnblogs是Consumer,而用户是User.协议的

OAuth授权登录

一.写在前面 日常生活中,我们经常看到到一个网站时,需要登录的时候,都提供了第三方的登录,也就是说你可以使用你的微信,QQ,微博等账号进行授权登录.那么这个认证登录的东西到底是什么呢? 微信授权登录页面 或者说你实现这样的授权登录,该怎么做呢?我觉得思路: 首先是登录的网站时,去在第三方登录后,第三方回调登录网站的接口,然后网站这边拿到第三方的已经登录状态,就可以在网站本身登录了.就相当于微博微信就是你的登录用户名和密码的校验. 二.OAuth授权登录 解决上面的问题,就能用到OAUTH协议.

基于 OAuth 安全协议的 Java 应用编程

OAuth 简介 OAuth 是由 Blaine Cook.Chris Messina.Larry Halff 及 David Recordon 共同发起的,目的在于为 API 访问授权提供一个安全.开放的标准. 基于 OAuth 认证授权具有以下特点: 安全.OAuth 与别的授权方式不同之处在于:OAuth 的授权不会使消费方(Consumer)触及到用户的帐号信息(如用户名与密码),也是是说,消费方无需使用用户的用户名与密码就可以申请获得该用户资源的授权. 开放.任何消费方都可以使用 OA