资源受权?对OAuth2.0的一次从新认识的过程

什么是OAuth?

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

OAuth分为OAuth1.0和OAuth2.0两个版本,后来随着OAuth2.0被使用的愈来愈普遍,OAuth1.0逐渐退出舞台(固然仍有少部分系统在使用1.0受权标准)。下面咱们围绕OAuth2进行展开。前端

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

咱们以博客园登陆为例:后端

新同窗小明想在“博客园”发表文章,这时候他进入登陆页面,“博客园”登陆首页须要小明提供用户名和密码才容许小明登入。浏览器

 而因为小明是第一次使用“博客园”,他对博客园可能不是很信任,因而他想经过下方的他信任QQ应用直接登陆。服务器

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

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

OAuth2四个参与角色

1.资源全部者(Resource Owner):资源的拥有者(上例中:小明)
2.资源服务器(Resource Server):资源所在的服务器(上例中:QQ应用)
3.受权服务器(Authorization Server):用于验证client(第三方应用)的真实性,提供受权码和令牌token。受权服务器可单独部署,也能够和资源服务器一块儿部署。
4.第三方应用(Client):访问受保护资源的客户端,上例中:博客园

这里,不少同窗会对“受权服务器”存在疑惑,上例中博客园登陆流程并未体现受权服务器啊?咱们接着往下看post

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的四种方式

相关文章
相关标签/搜索