什么是OAuth?

OAuth一个开放的授权标准,允许用户在不提供关键信息(如账号,密码)给第三方应用的前提下,让第三方应用去访问用户在某网站上的资源(如头像,用户昵称等)

OAuth分为OAuth1.0和OAuth2.0两个版本,后来随着OAuth2.0被使用的越来越广泛,OAuth1.0逐渐退出舞台(当然仍有少部分系统在使用1.0授权标准)。下面我们围绕OAuth2进行展开。

OAuth 2.0致力于简化客户端开发人员的工作,同时为Web应用程序,桌面应用程序,移动电话和客厅设备提供特定的授权流程。

我们以博客园登录为例:

新同学小明想在“博客园”发表文章,这时候他进入登录页面,“博客园”登录首页需要小明提供用户名和密码才允许小明登入。

而由于小明是第一次使用“博客园”,他对博客园可能不是很信任,于是他想通过下方的他信任QQ应用直接登录。

来到这里我们发现,通过授权,“博客园”将获得小明在QQ应用中的资源(昵称,头像,性别),并成功登录“博客园”,而并不需要提供用户名和密码给“博客园”。

上例中“博客园”就是所谓的第三方应用,而QQ就是提供受保护资源的某个应用。

OAuth2四个参与角色

1.资源所有者(Resource Owner):资源的拥有者(上例中:小明)

2.资源服务器(Resource Server):资源所在的服务器(上例中:QQ应用)

3.授权服务器(Authorization Server):用于验证client(第三方应用)的真实性,提供授权码和令牌token。授权服务器可单独部署,也可以和资源服务器一起部署。

4.第三方应用(Client):访问受保护资源的客户端,上例中:博客园

这里,很多同学会对“授权服务器”存在疑惑,上例中博客园登录流程并未体现授权服务器啊?我们接着往下看

OAuth2标准授权流程

结合OAuth2经典流程图,我们一下再来看下小明登录“博客园”的流程。

(A)第三方应用(client)“博客园”向(资源拥有者)小明发起授权请求,即小明点击博客园登录页中的QQ登录。

(B)QQ登录授权页面,小明登录自己的QQ账号,同意授权给“博客园”,并返回授权许可凭证。

(C)第三方应用(client)“博客园”拿着步骤(B)获取的授权许可凭证,向授权服务器发起请求。

(D)授权服务器同意第三方应用(client)“博客园”的请求,并返回一个令牌Token。

(E)第三方应用(client)“博客园”拿着Token请求(资源服务器)QQ应用中的昵称,头像等资源

(F)(资源服务器)QQ应用验证Token通过,并返回资源给第三方应用(client)“博客园”

通过上述流程,我们可以看出,当QQ授权同意后,并不是马上就将QQ应用中的资源返回给第三方客户端的,而是需要客户端拿着授权许可凭证,向授权服务器请求并获取最终的钥匙Token,然后才能获得受保护资源。

显然,授权服务器充当了一个验证client,并颁发token令牌的服务角色。

那么授权许可凭证到底是什么呢?

OAuth2授权许可凭证

1.授权码(Authorization Code):

该模式目前是功能最完整、流程最严密的授权模式。一般需要client有专门的后端server,根据获取的授权码code在后端server请求令牌token。

上例中博客园登录授权就是用的“授权码模式”,交互流程如下:

1)博客园向小明发起QQ授权请求。

2)QQ授权验证同意后,根据博客园提供的Redirect_url返回,并带上授权码code

3)博客园前端根据返回的url获取授权码code,并在后端server向授权服务器发起请求获取token

4)授权服务验证通过,并以json格式返回token

5)博客园再根据token请求QQ应用中获取受保护资源(头像,昵称等)

步骤(1),授权请求(Authorization Request):

client需提供如下主要参数:

   1.client_id:必填,第三方应用唯一标识ID

   2.redirect_uri:必填,授权同意后,重定向地址URL

   3.response_type:必填,授权码模式下固定值为“code”

   4.state:选填,一个状态码,可用于防止跨站请求伪造(CSRF)攻击。客户端发起授权请求时会生成一个状态码与客户端绑定,授权请求成功后会将该state原样返回

   5.scope:选填,标识授权范围

例如博客园向QQ发起授权请求:

https://graph.qq.com/oauth2.0/show?which=Login&display=pc
&client_id=101880508
&scope=get_user_info
&response_type=code
&redirect_uri=***
&state=*****

扩展:跨站请求伪造(CSRF)攻击:用户登录了A可信网站,认证信息保存在浏览器cookie中。当用户访问攻击者创建的B网站时,用户认证信息仍有效,攻击者通过在B网站发送一个伪造的请求提交到A网站服务器上,让A网站服务器误以为请求来自于自己的网站。

步骤(2),授权请求同意后,返回信息:

  1.code:授权码

  2.state:原样返回,client提交的state状态码

步骤(3),根据授权码code,后端请求token,client需提供如下参数

1.grant_type:必填。授权码模式,固定值“authorization_code”。

2.code : 必填。授权同意后返回的授权码。

3.redirect_uri:必填。授权同意后,重定向地址URL
4.client_id:必填。第三方应用唯一标识ID。
5.client_secret:必填。第三方应用授权申请的秘钥。

例如:

POST /oauth/token HTTP/1.1
Host: authorization-server.com grant_type=authorization_code
&code=xxxxxxxxxxx
&redirect_uri=https://example-app.com/redirect
&client_id=xxxxxxxxxx
&client_secret=xxxxxxxxxx

步骤(4),授权认证通过,返回主要参数。

1.access_token:访问令牌。

2.refresh_token:刷新令牌。

3.expires_in:令牌过期时间。
4.token_type:令牌类型。

其中刷新令牌refresh_token的作用是,当访问令牌token失效时,无需重新发起授权获取新的token,根据刷新令牌直接请求授权服务,就可以获取新的令牌。

2.隐式许可(Implicit):

授权码模式的简化应用,跳过了获取授权码code的过程,直接获取token。一般用于没有后端的Client。

如果博客园使用该模式,其工作流程:

1)博客园向小明发起QQ授权请求。

2)QQ授权验证同意后,根据博客园提供的Redirect_url返回,并带上令牌token

3)博客园再根据token请求QQ应用中获取受保护资源(头像,昵称等)

步骤(1),授权请求参数和授权码模式参数一样,唯一不同的参数是response_type,Implicit模式下固定值为“token”。

步骤(2),授权请求同意后,返回信息:

1.access_token:访问令牌。
2.token_type:令牌类型。
3.expires_in:令牌过期时间。

注:隐式授权模式颁发的令牌,不提供refresh刷新令牌

URL格式:

格式:https://a.com/callback#token=ACCESS_TOKEN

注意,令牌的位置是 URL 锚点“#”后面,而不是查询字符串“?”后面,这是因为 OAuth2允许跳转网址是 HTTP 协议,因此存在"中间人攻击"的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。

3.用户密码模式(Resource Owner Password Credentials):

客户端提供用户名和密码,获取token。前面我们说OAuth2就是为了避免直接提供用户名和密码给第三方应用程序而诞生,那么这里又是怎么回事呢?

其实,该授权模式的初衷是为服务自己的应用启用密码登录,用户使用其用户名和密码登录该服务的网站或本机应用程序,但是绝对不允许第三方应用程序询问用户密码。

授权请求,提供参数:

1.grant_type:必填。该模式下固定值为“password”。

2.username:必填。用户登陆名。

3.passward:必填。用户登陆密码。

4.scope:可填。表示授权范围。
5.客户端认证参数:通常如果授权服务管理系统给客户端颁发了身份秘钥信息(client_id,client_secret),那么客户端发起授权请求时需要携带参数client_id和client_secret。或在HTTP Basic auth标头中接受客户端client_secret和密码client_secret

其中,客户端认证参数:client_id和client_secret主要是用于授权服务验证客户端的身份。如果客户端都没在授权服务管理系统备案(不需要验证客户端身份),那么授权请求就不需要这两个参数。备案又是什么呢?大家请留意文章末尾。

以postman请求token为例:

第一种方式:将client_id和client_secret作为请求体参数

第二种方式:在HTTP Basic auth请求头中单独验证client_secret和client_secret

授权请求同意后,返回主要参数:

1.access_token:访问令牌。

2.token_type:令牌类型。

3.expires_in:令牌过期时间。

4.scope:授权范围

4.客户端模式(Client Credentials):

当第三方应用程序请求访问令牌以访问其自己的资源(而非代表其他用户去访问资源)时,使用该模式。此时第三方应用程序将自己当成资源所有者,直接请求授权服务器获取令牌token。

授权请求,提供参数:

1.grant_type:必填。该模式下固定值为“client_credentials”。

2.scope:可填。表示授权范围。

3.客户端认证:必填,包含参数client_id和client_secret;或在HTTP Basic auth标头中接受客户端client_secret和密码client_secret

以postman请求token为例:

第一种方式:将client_id和client_secret作为请求体参数

第二种方式:在HTTP Basic auth请求头中单独验证client_secret和client_secret

两种方式效果一致,都是通过client_id和client_secret,让授权服务器验证客户端的身份。

授权请求同意后,返回参数:

1.access_token:访问令牌。

2.token_type:令牌类型。

3.expires_in:令牌过期时间。

4.scope:授权范围

扩展:第三方应用发起授权请求时,client_id和client_secret是哪来的呢?

授权服务提供第三方应用的管理:

第三方应用申请令牌之前,都必须先到授权服务系统备案,说明自己的身份,然后会拿到两个身份识别码:客户端 ID(client ID)和客户端密钥(client secret)。这是为了防止令牌被滥用,没有备案过的第三方应用,是不会拿到令牌的。

5.刷新令牌refresh  token

前面我们说,当授权请求同意后,通常授权服务器会返回一个刷新令牌refresh  token给我们(该返回参数非必选的,由授权服务定制,通常推荐返回该参数)。

当访问令牌access token 过期后,如果重新发起一遍请求令牌的过程显然有点麻烦,这时候通过refresh token发起一次请求可以直接获取新的访问令牌access token。

请求参数:

1.grant_type:必填。固定值为“refresh_token”。

2.refresh_token:必填。

3.scope:可填。表示授权范围。

4.客户端认证:通常如果授权服务管理系统给客户端颁发了身份秘钥信息(client_id,client_secret),那么客户端发起授权请求时需要携带参数client_id和client_secret。或在HTTP Basic auth标头中接受客户端client_secret和密码client_secret。
如果客户端不需要身份认证,则无需携带任何身份认证的信息

例如:

POST /oauth/token HTTP/1.1
Host: authorization-server.com grant_type=refresh_token
&refresh_token=xxxxxxxxxxx
&client_id=xxxxxxxxxx
&client_secret=xxxxxxxxxx

本文,我们结合博客园授权QQ登录的案例,描述了OAuth2的基本概念,OAuth2的授权流程以及各种授权模式的使用。多动手,多动手,多动手才能加深自己的理解。

附:推荐几篇值得学习的OAuth2文章

1.OAuth2.0协议标准

2.大神阮一峰的文章:OAuth2.0的四种方式

资源授权?对OAuth2.0的一次重新认识的过程的更多相关文章

  1. QQ第三方授权登录OAuth2.0实现(Java)

    准备材料 1.已经备案好的域名 2.服务器(域名和服务器为统一主体或域名已接入服务器) 3.QQ号 4.开发流程:https://wiki.connect.qq.com/%E5%87%86%E5%A4 ...

  2. 夺命雷公狗---微信开发53----网页授权(oauth2.0)获取用户基本信息接口(3)实现世界留言版

    前面两节课我们讲的是base型的授权了,那么现在我们开始Userinfo型授权, 先来看下我们的原理图 我们这节课来做一个 世界留言版 系统 1..首先我还是在微信测试平台那里设置好回调页面的域名 2 ...

  3. 夺命雷公狗---微信开发51----网页授权(oauth2.0)获取用户基本信息接口(1)

    如果用户在微信客户端访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,从而实现业务逻辑. 一般我们用来“数据采集”,“市场调查”,“投票”,只要授权了第三方网页,微信用户无需注册就可 ...

  4. 【第二十一篇】手C# MVC 微信授权登录 OAuth2.0授权登录

    首先一定要熟读,最起码过一遍微信开发者文档 微信开发者文档 文档写的很清楚 授权登录四步走 在正文开始前,我得讲清楚一个事情 敲黑板,划重点:微信一共有两个 access_token 一个是7200就 ...

  5. 夺命雷公狗---微信开发52----网页授权(oauth2.0)获取用户基本信息接口(2)

    我们在上一节课已经发送code给第三方了,那么这就要获取code去换取到用户的openid. 第一步:编写create_baseurl.php(上一节课程已经写完了) 第二步:编写vote1.php( ...

  6. OAuth2.0授权机制说明

    授权机制说明   1 简介 优酷对第三方应用用户授权采用OAuth2.0标准 2 OAuth2.0 授权方式 优酷支持OAuth 2.0的三种授权方式,请根据平台选用不同的授权方式: 2.1 通用授权 ...

  7. OAuth2.0 基础概述

    web:http://oauth.net/2/ rfc:http://tools.ietf.org/html/rfc6749 doc:http://oauth.net/documentation/ c ...

  8. 理解OAuth2.0认证

    一.什么是OAuth协议 OAuth 协议为用户资源的授权提供了一个安全的.开放而又简易的标准.与以往的授权方式不同之处是 OAuth的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方 ...

  9. OAuth2.0 与 oauth2-server 库的使用

    作者:baiyi链接:https://www.jianshu.com/p/83b0f6d82d6c來源:简书 OAuth2.0 是关于授权的开放网络标准,它允许用户已第三方应用获取该用户在某一网站的私 ...

随机推荐

  1. 使用VMware WorkStation虚拟机软件安装CentOS 8

    使用VMware WorkStation虚拟机软件安装CentOS 8 说明:本章我们使用的虚拟机软件是VMware WorkStation15.5 PRO,镜像包是CentOS-8.2.2004-x ...

  2. Codeforces Round #625 Div. 2 D E

    D题:https://codeforces.com/contest/1321/problem/D 题意:题目给个有向图,然后给一段序列,我们要沿着这个序列走,问走的过程中当前点到t的最短路会重构多少次 ...

  3. HDU5732 Subway【树重心 树哈希】

    HDU5732 Subway 题意: 给出两棵大小为\(N\)的同构树,要求输出对应的节点 \(N\le 10^5\) 题解: 由于重心最多只有两个,找到重心之后以重心为根进行树哈希,找到相同哈希值的 ...

  4. zjnu1749 PAROVI (数位dp)

    Description The distance between two integers is defined as the sum of the absolute result of subtra ...

  5. HDU - 2159 dp

    题目: 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务.久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级.现在的问题是,xhd升掉最后一级还 ...

  6. WPF Animation For SizeChanged Of UIElement

    效果图 学到一个新词: Show me the money 背景 这几天查资料,看到 CodeProject 上面的一篇 Post <Advanced Custom TreeView Layou ...

  7. 深入了解typeof与instanceof的使用场景及注意事项

    JavaScript中的数据类型分为两类,undefined,number,boolean,string,symbol,bigint,null[1]组成的基础类型和Object.Function.Ar ...

  8. ssh原理及加密传输

    1.ssh??(保证过程中是加密的,即安全的)ssh 是 Secure Shell 的缩写,是一个建立在应用层上的安全远程管理协议.ssh 是目前较为可靠的传输协议,专为远程登录会话和其他网络服务提供 ...

  9. 【原创】k8s之job和Cronjob

    1.失败任务 apiVersion: batch/v1 kind: Job metadata: name: bad spec: template: metadata: name: bad spec: ...

  10. LCIS(最长公共上升子序列)模板

    求出LCIS并输出其路径. 1 #include <iostream> 2 #include <cstdio> 3 #include <string> 4 #inc ...