OAuth协议详解,OAuth1.0到OAuth2.0(总结)

文章干货内容较多,请耐心观看

1、什么是OAuth协议,OAuth 1.0(2007~-2012)

OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。简单来说就是提供除了"账户密码"验证方式以外的验证授权方式。

1.1 应用场景如下

如果一个用户拥有两项服务:一项服务是图片在线存储服务A,另一个是图片在线打印服务B。如下图所示。由于服务A与服务B是由两家不同的服务提供商提供的,所以用户在这两家服务提供商的网站上各自注册了两个用户,假设这两个用户名各不相同,密码也各不相同。当用户要使用服务B打印存储在服务A上的图片时,用户该如何处理?法一:用户可能先将待打印的图片从服务A上下载下来并上传到服务B上打印,这种方式安全但处理比较繁琐,效率低下;法二:用户将在服务A上注册的用户名与密码提供给服务B,服务B使用用户的帐号再去服务A处下载待打印的图片,这种方式效率是提高了,但是安全性大大降低了,服务B可以使用用户的用户名与密码去服务A上查看甚至篡改用户的资源。
在这里插入图片描述
很多公司和个人都尝试解决这类问题,包括Google、Yahoo、Microsoft,这也促使OAUTH项目组的产生。OAuth是由Blaine Cook、Chris Messina、Larry Halff 及David Recordon共同发起的,目的在于为API访问授权提供一个开放的标准。OAuth规范的1.0版于2007年12月4日发布。通过官方网址:http://oauth.net可以阅读更多的相关信息。

1.2 OAUTH角色定义

OAuth1.0协议中,一共定义了三种关键角色:

  • Service Provider:(服务提供商)允许通过OAuth访问的网络服务、平台、应用等,比如腾讯一般都是扮演这种角色的;
  • User:(用户)在Service Provider那里拥有帐号的人,称为用户,比如QQ用户一般都扮演这个角色;
  • Consumer:(接入者)通过OAuth访问User在Service Provider处存储的受保护的隐私数据的网络服务、应用等;

1.3 OAUTH相关术语

在弄清楚OAUTH流程之前,我们先了解下OAUTH的一些术语的定义:

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响应代码:

400 401 等Http协议代码

OAUTH六大协议要素

  1. Consumer Key:接入者在服务提供商处的唯一标识符,一个字符串;
  2. Consumer Secret:与Consumer Key关联的密码;
  3. Request Token:接入者用于取得用户授权的一个载体,由Service Provider颁发,然后请求用户的授权;
  4. Access Token:接入者访问存储于Service Provider的隐私信息的凭证,可以用经过用户授权的Request Token交换;
  5. Token Secret:与Token关联的一个密码,Request Token和Access Token都有各自与之关联的密码;
  6. Signature:所有授权流程中的关键步骤,都要求签名,签名使用双方约定的算法,可以被验证,这是安全性的来源,因为OAuth1.0是不依赖TLS/SSL的;

2、OAUTH 1.0 认证授权流程

认证流程如下:

  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也可能不返回。

E. Request Token 授权后,使用者将向Access Token URL发起请求,将上步授权的Request Token换取成Access Token。请求的参数见上图,这个比第一步A多了一个参数就是Request Token。

F. OAUTH服务提供商同意使用者的请求,并向其颁发Access Token与对应的密钥,并返回给使用者。

G. 使用者以后就可以使用上步返回的Access Token访问用户授权的资源。

从上面的步骤可以看出,用户始终没有将其用户名与密码等信息提供给使用者(第三方软件),从而更安全。用OAUTH实现背景一节中的典型案例:当服务B(打印服务)要访问用户的服务A(图片服务)时,通过OAUTH机制,服务B向服务A请求未经用户授权的Request Token后,服务A将引导用户在服务A的网站上登录,并询问用户是否将图片服务授权给服务B。用户同意后,服务B就可以访问用户在服务A上的图片服务。整个过程服务B没有触及到用户在服务A的帐号信息。如下图所示,图中的字母对应OAUTH流程中的字母:
在这里插入图片描述

流程简要总结:

  1. 接入者向服务提供商申请Request Token;
  2. 接入者引导用户到服务提供商处授权请求;
  3. 用户授权;
  4. 服务提供商将用户重定向回接入者的网站,并带回授权过的Request Token;
  5. 接入者使用Request Token向服务提供商交换Access Token;
  6. 接入者通过Access Token访问用户在服务提供商处存储的受保护的资源;

3、为什么出现OAuth 2.0 (2011-~)

上述描述的是OAuth 1.0 协议最初的标准,随着时间的发展,发现了其中存在重大漏洞,后来协议进行完善,可以认为出现了OAuth 1.0a版本,详细可参考https://blog.csdn.net/joeyon1985/article/details/42026039
https://blog.csdn.net/joeyon1985/article/details/42025477 ,文章中详细介绍了协议的漏洞之处以及如何进行的修复(1.0a版本)。
实际上OAuth1.0 最终版(已经成为RFC5849 标准)已经没有这个安全的漏洞了,但是OAuth 协议( RFC5849 标准)文档上提出了以下安全考量,对应 http://tools.ietf.org/html/rfc5849#section-4

  1. 似乎说 RSA_SHA1 更安全

  2. 建议用 SSL 或者 TLS 保证请求的安全

  3. 建议用 SSL 或者 TLS 保证确认服务提供者的身份

  4. 客户端 proxy 或者 cache 的安全

  5. 服务端密钥的安全存储

  6. 客户端密钥的安全存储

  7. 警告用户,防止用户的疏忽

  8. 由于第三方应用的不可信任(可能希望获取更多的用户资源),需对授权的资源严格的分类,并告知明确用户可能存在的风险

  9. 密钥的安全性,最好是真正的随机数

  10. DOS/DDOS 攻击

  11. SHA-1 自身的漏洞

  12. 签名只是保证了 base_string 的完整

  13. CSRF ( Cross Site Request Forgery )

  14. Clickjacking

  15. 客户端密钥的安全

协议 1.0 定稿后,已经广泛使用,其本身不会有什么安全漏洞,但协议的实现可能存在漏洞,这是我们需要花精力去测试的。由于参数众多,实现复杂,加上以上对于安全考量的思考,2012年OAtuh 2.0 协议发布。
2012年10月,OAuth 2.0协议正式发布为RFC 6749。现在百度开放平台,腾讯开放平台等大部分的开放平台都是使用的OAuth 2.0协议作为支撑。

4、OAuth 2.0 介绍

在OAuth 2.0的认证和授权的过程中主要包括以下角色定义:

  • Resource owner: 资源所有者(通常指用户或者提供资源服务的平台)
  • Resource server:资源服务器(托管受保护资源的服务器)
  • Client:客户端(浏览器、APP)
  • Authorization server:授权服务器(颁发访问令牌、验证令牌、刷新令牌)

4.1 交互过程

OAuth 在 “客户端” 与 “服务提供商” 之间,设置了一个授权层(authorization layer)。“客户端” 不能直接登录 “服务提供商”,只能登录授权层,以此将用户与客户端区分开来。“客户端” 登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。“客户端” 登录授权层以后,“服务提供商” 根据令牌的权限范围和有效期,向 “客户端” 开放用户储存的资料。
在这里插入图片描述

4.2 四种授权模式

RFC 6749 中写到:(由于互联网有多种场景,)本标准定义了获得令牌的四种授权方式(authorization grant )。
这四种模式如下:

  • 授权码(authorization-code)
  • 隐藏式(implicit)
  • 密码式(password)
  • 客户端凭证(client credentials)

4.2.1 授权码(authorization-code)模式

授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
在这里插入图片描述
过程如下:

  1. 第一步,A 网站提供一个链接,用户点击后就会跳转到 B 网站,授权用户数据给 A 网站使用。下面就是 A 网站跳转 B 网站的一个示意链接。
  2. 第二步,用户跳转后,B 网站会要求用户登录,然后询问是否同意给予 A 网站授权。用户表示同意,这时 B 网站就会跳回redirect_uri参数指定的网址。跳转时,会传回一个授权码,就像下面这样。
  3. 第三步,A 网站拿到授权码以后,就可以在后端,向 B 网站请求令牌。
  4. 第四步,B 网站收到请求以后,就会颁发令牌。具体做法是向redirect_uri指定的网址,发送一段 JSON 数据。

4.2.2 隐藏式(implicit)模式

有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)“隐藏式”(implicit)。
在这里插入图片描述

过程如下:

  1. 第一步,A 网站提供一个链接,要求用户跳转到 B 网站,授权用户数据给 A 网站使用。
  2. 第二步,用户跳转到 B 网站,登录后同意给予 A 网站授权。这时,B 网站就会跳回redirect_uri参数指定的跳转网址,并且把令牌作为 URL 参数,传给 A 网站。

这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。

4.2.3 密码式(password)模式

如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。
过程如下:

  1. 第一步,A 网站要求用户提供 B 网站的用户名和密码。拿到以后,A 就直接向 B 请求令牌。
  2. 第二步,B 网站验证身份通过后,直接给出令牌。注意,这时不需要跳转,而是把令牌放在 JSON 数据里面,作为 HTTP 回应,A 因此拿到令牌。

这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。

4.2.4 客户端凭证(client credentials)模式

最后一种方式是凭证式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌。
过程如下:

  1. 第一步,A 应用在命令行向 B 发出请求。
  2. 第二步,B 网站验证通过以后,直接返回令牌。

这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。

4.3 令牌的使用

A 网站拿到令牌以后,就可以向 B 网站的 API 请求数据了。

此时,每个发到 API 的请求,都必须带有令牌。具体做法是在请求的头信息,加上一个Authorization字段,令牌就放在这个字段里面。

curl -H "Authorization: Bearer ACCESS_TOKEN" \
"https://api.b.com"

上面命令中,ACCESS_TOKEN就是拿到的令牌。

4.4 令牌的刷新

令牌的有效期到了,如果让用户重新走一遍上面的流程,再申请一个新的令牌,很可能体验不好,而且也没有必要。OAuth 2.0 允许用户自动更新令牌。

具体方法是,B 网站颁发令牌的时候,一次性颁发两个令牌,一个用于获取数据,另一个用于获取新的令牌(refresh token 字段)。令牌到期前,用户使用 refresh token 发一个请求,去更新令牌。

5、OAuth 1.0 和 2.0 对比

- OAuth1.0 OAuth2.0
是否兼容 - OAuth 2.0是个全新的协议
token有效期 有效期非常长的token(典型的是一年有效期或者无有效期限制) 短有效期的access token和长生命期的refresh token。这将允许客户端无需用户再次操作而获取一个新的access token,并且也限制了access token的有效期
协议 http https
过程 伴随复杂的签名算法等 轻量,提供多种方式

------------------------------------------- 参考博文 -------------------------------------
https://blog.csdn.net/hereweare2009/article/details/3968582
https://blog.csdn.net/joeyon1985/article/details/42026039
https://blog.csdn.net/joeyon1985/article/details/42025477
https://blog.csdn.net/qq_28077405/article/details/105549707
http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html

猜你喜欢

转载自blog.csdn.net/qq_38941937/article/details/112444312