OAuth2基础学习

OAuth 2.0 学习

这篇博客本人不知道该怎么定义,因为我是看了一些博客和视频想总结一下,其中cheat的成分肯定不在少数,所以我觉得在一开始都贴出来好了,这样不懂了随时还可以回去看一看困扰自己的问题是不是前人早就踩过坑了。顺便总结一下,好好学习每一天。最终会声明转载自阮一峰老师的博客。后续可能会在使用时再做实战总结以及通读RFC6749的工作

  • B站UP主魔王不造反的视频:彻底理解OAuth2协议
  • 阮一峰博客:理解OAuth2协议
  • 阮一峰博客:OAuth2的一个简单解释 我觉得系统看完一次OAuth2协议之后再来读一次这个文章应该更好
  • 阮一峰博客:OAuth 2.0 的四种方式
  • 阮一峰博客:GitHub OAuth 第三方登录示例教程
  • 关于 OAuth2.0 安全性你应该要知道的一些事

基本概念

引入场景

假设你居住在北京海淀区中心的一个小区,最近比较忙没有时间自己做饭,经常需要定外卖。但是小区设有门禁卡,外卖员每次进入的时候都要经历门禁这一关,非常麻烦。所以你希望能有一种方法能让外卖员自己通过门禁进入小区。

你可能想把自己的门禁卡给外卖员,这显然不合适,因为你不知道第二天你要定哪一家,而且突然不想让这个外卖员进入小区了也是非常麻烦的。

于是你向小区门禁的程序员建议开发一个授权系统,当外卖员要进入小区时,只需要点击门口的请求授权按钮,你的手机上就会弹出这个外卖员的信息(姓名、电话、店名),如果你点击授权,外卖员就会获得一个有效期七天的令牌(token),接下来外卖员就可以用这个令牌通过所有被授权的小区的门禁。

这个流程大概就是计算机网络中的OAuth2的大概流程。

前置知识

这里介绍几个可能在后面用到的名词:

  • Third-party Application:第三方应用程序,本文中又称为客户端(Client)。
  • HTTP Service:HTTP服务提供商
  • Resource Owner:资源所有者,也就是用户(User)
  • User Agent:用户代理,一般也就是指浏览器
  • Authorization Server:认证服务器,即服务提供商专门用来处理认证的服务器
  • Resource Server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器可以是同一台服务器也可以不是。

OAuth 是什么?

OAuth:Open standard for Authorization

OAuth是一个关于授权的开放网络的标准,它的作用就是“客户端”安全可控地获取“用户”的授权,与“服务提供商”进行互动。它可以授权一个第三方的网站或者APP去访问他们在特定网站上的信息,而无需向第三方的网站或者应用提供账号密码。

简单说,OAuth是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。

OAuth 中有什么角色?

  • resource owner:资源拥有者,一般指的就是用户
  • resource server:资源服务器
  • client:客户端,也就是第三方应用程序
  • authorization server:认证服务器

Ruby-China使用Github第三方登录实例分析(例子样例取自视频,上面已经贴了链接)

首先打开ruby-china的登录页面

https://ruby-china.org/account/sign_in

OAuth2基础学习_第1张图片

常规的登录方法是 输入账号和密码,而这个网站也为我们提供了一个使用Github平台登录的方法。

点击这个GitHub这个按钮

OAuth2基础学习_第2张图片

这个是我拷贝下来的链接

https://github.com/login/oauth/authorize?client_id=f252166dc176d078abac&redirect_uri=https%3A%2F%2Fruby-china.org%2Faccount%2Fauth%2Fgithub%2Fcallback&response_type=code&state=193643c5105270c202a459fc95c29aa69415a6d8f8b7987f

然后我们看到了一个授权的按钮,一旦授权成功,ruby-China就可以访问本人GitHub账户上的一系列信息,头像、邮箱还有昵称信息。

而传统的模式如果填写了用户名和密码,ruby-China就获得了我的用户名和密码,这一切都基于这个站点是我信任的,如果是一个小众的站点,他可能会保存我的输入,甚至用我的账户去做一些非法的事情。而且信息会被泄露。这也是开发OAuth的原因。

点击授权后

点击授权后,Ruby-China就得到了用户在GitHub上存储的允许访问的账户信息。

所以,OAuth2解决了什么问题呢?

我们知道任何的身份鉴别本质上都是基于对请求方的不信任所产生的。 用户可能并不信任这个站点,但是用户信任GitHub。身份鉴别就是为了解决身份的可信任问题。

新的疑问?GitHub为什么信任Ruby-China?

Ruby-China需要去GitHub去申请一个第三方应用,去申请特定的标识符。

###分析流程

OAuth2基础学习_第3张图片

上面的例子说明中:OAuth2的四个角色以及在这个例子中它们对应的实体

  • resource owner:资源拥有者,一般指的就是用户
    • 用户 user
  • resource server:资源服务器,存储用户的信息
    • 可与认证服务器相同,我认为是GitHub
  • client:客户端,也就是第三方应用程序
    • Ruby-China
  • authorization server:认证服务器
    • GitHub

流程如下:

  • 用户打开客户端之后,客户端要求用户给予授权。
  • 用户同意给客户端授权
  • 客户端使用上一步给予的授权,向认证服务器申请令牌(token)。(这个token是GitHub颁发给Ruby-China的)
  • 认证服务器对客户端进行认证,认证无误后,同意发放令牌。
  • 客户端使用令牌,向资源服务器申请获取资源。
  • 资源服务器确认令牌无误,同意向客户端开发受保护资源。(实际上这里要根据客户端所具有的权限,并不是把所有资源都开放)

其中最重要的一点就是第二步:用户给客户端授权。

我们刚刚还有一个问题:Github为什么信任Ruby-China?

OAuth需要用户授权客户端,那么客户端需要持有什么信息呢?

  • 应用名称
  • 应用网站
  • 重定向URI或回调URL(redirect_uri)
  • 客户端标识 client_id
  • 客户端密钥 client_secret 用于加密token

第三方应用申请token之前,都必须先到授权服务器备案,说明自己的身份。然后就会得到两个身份标识码:Client ID 和Client Secret。这是为了防止token被滥用。没有备案过的第三方应用无法得到token。

OAuth2基础学习_第4张图片

OAuth2基础学习_第5张图片

接下来是客户端的授权模式

客户端授权模式(图片取自RFC6749)

客户必须得到用户的授权(Authorization Grant),才能获得令牌(Access Token)。基于不同的互联网应用场景,OAuth2中定义了四种授权方式。

  • 授权码模式(Authorization Code)
  • 简化模式(Implicit)
  • 密码模式(Resource Owner Password Credentials)
  • 客户端模式(Client Credentials)

授权码模式(Authorization Code)

授权码模式指的是第三方应用先申请一个授权码,再使用该授权码获取token。

OAuth2基础学习_第6张图片

这种模式功能最完整,也是流程最严密的。主要是通过客户端(Ruby-China)和授权服务器(GitHub)进行交互,多用于Web应用。授权码通过前端传送,token则存储在后端,而且所有与资源服务器的通信都在后端完成,可以避免token泄露。

客户端通过User-Agent来访问,也就是通过浏览器 来访问。

再来看一下GitHub授权Ruby-China的过程

OAuth2基础学习_第7张图片

点击之后,它跳转到了:

OAuth2基础学习_第8张图片

这个页面,它的地址我们前面已经做了记录,我们对这个URL做一个处理,为了可以看得清楚一些:

client_id=f252166dc176d078abac
redirect_uri=https%3A%2F%2Fruby-china.org%2Faccount%2Fauth%2Fgithub%2Fcallback
response_type=code
state=193643c5105270c202a459fc95c29aa69415a6d8f8b7987f

我们可以看到client_id(唯一标识Ruby-China)和重定向的URI(点击授权之后会重定向到这个地址),还有response_type与客户端授权模式相关,对于授权码模式来说,就是code。state表示一个本地的状态, 可以理解成是Ruby-China生成的一个随机数,当授权成功之后GitHub会把这个随机数再次发给Ruby-China ,可以确认确实是GitHub发送的,主要是为了防止CSRF攻击;state这个参数是可选的,但是推荐选上。

当点击授权之后,会跳转回到Ruby-China的网页,并提示登录成功!

OAuth2基础学习_第9张图片

在这个过程中,Github还会向Ruby-China发送一个请求,请求的地址就是重定向的地址,请求参数包括:code、state,接下来Ruby-China后台可以使用code、client_id和client_secret来获取Access Token。通过token就可以去GitHub的资源服务器申请一些信息。

授权码模式的具体参数:

字段 描述
Response_type 必填,固定为code,表示这是一个授权码模式请求。
Client_id 必填,在授权服务器注册应用后获得的唯一标识。
Redirect_uri 可选,注册时填写的重定向URI。
Scope 可选,请求资源范围,由逗号隔开,表示token代表的权限是什么。
State 推荐,如果存在,需要原样返回给客户端。

因为token可能会过期,所以由提出了一个refresh_token,用于更新token,获取下一次访问需要的token。在授权成功会会返回一个json信息:

{    
  "access_token":"ACCESS_TOKEN", // token信息
  "token_type":"bearer", // token类型,一般为bearer或mac,bearer需要依赖https的安全性且短期有效,需要refresh_token来刷新
  "expires_in":2592000, // 过期时间
  "refresh_token":"REFRESH_TOKEN", // 刷新token 用于获取下一次token 
  "scope":"read", // 权限范围,这里为read-only
  "uid":100101,
  "info":{...}
}

简化模式(Implicit)

OAuth2基础学习_第10张图片

同意授权后,授权服务器直接把token放到重定向URI中返回回来了。不传code而是直接传token,这里token对用户是可见的,而且客户端也不需要被授权服务器认证,不推荐这种 方式。

密码模式(Resource Owner Password Credentials)

OAuth2基础学习_第11张图片

这种模式下,用户向客户端提供自己的账号和密码(GitHub上的),客户端使用这些信息向服务提供商来获取token。用户必须对客户端绝对信任才行。

客户端模式(Client Credentials)

OAuth2基础学习_第12张图片

客户端以自己的名义向授权服务器请求一个认证,直接通过客户端的密钥和id获取token,无需用户参与。比较适合为消费者设计。不支持refresh_token。

Token与Password

令牌token和口令password的作用都是为了让用户安全进入系统,差异如下:

  1. token是短期的,到期会自动失效,用户自己不能修改。Password一般长期有效,如果用户自己不修改就不会发生变化。
  2. token可以被数据所有者撤销,且撤销后会立即失效。密码一般不允许其他人撤销。
  3. token有一个权限范围,限制了登录者可以获取的权限大小;比如在网络中只读token就比读写token更安全。而password一般是完整权限。

使用token登录时,系统一般也不会做二次确认,所以token和password一样都需要保密好,泄露的后果是一样的。

你可能感兴趣的:(Web安全)