理解OAuth2.0认证与客户端受权码模式详解

1、什么是OAuth协议

    OAuth 协议为用户资源的受权提供了一个安全又简易的标准。与以往的受权方式不一样之处是 OAuth的受权不会使第三方触及到用户的账号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就能够申请得到该用户资源的受权,所以 OAuth是安全的。OAuth 是 Open Authorization 的简写web

    OAuth 自己不存在一个标准的实现,后端开发者本身根据实际的需求和标准的规定实现。其步骤通常以下:json

  1. 第三方要求用户给予受权后端

  2. 用户赞成受权api

  3. 根据上一步得到的受权,第三方向认证服务器请求令牌(token缓存

  4. 认证服务器对受权进行认证,确认无误后发放令牌安全

  5. 第三方使用令牌向资源服务器请求资源服务器

  6. 资源服务器使用令牌向认证服务器确认令牌的正确性,确认无误后提供资源微信

2、OAuth2.0是为了解决什么问题?

    任何身份认证,本质上都是基于对请求方的不信任所产生的。同时,请求方是信任被请求方的,例如用户请求服务时,会信任服务方。因此,身份认证就是为了解决身份的可信任问题。app

    在OAuth2.0中,简单来讲有三方:用户(这里是指属于服务方的用户)、服务方(如微信、微博等)、第三方应用编辑器

  1. 服务方不信任用户,因此须要用户提供密码或其余可信凭据

  2. 服务方不信任第三方应用,因此须要第三方提供自已交给它的凭据(如微信受权的code,AppID等)

  3. 用户部分信任第三方应用,因此用户愿意把自已在服务方里的某些服务交给第三方使用,但不肯意把自已在服务方的密码等交给第三方应用

3、OAuth2.0成员和受权基本流程

3.1 OAuth2.0成员

  1. Resource Owner(资源拥有者:用户)

  2. Client (第三方接入平台:请求者)

  3. Resource Server (服务器资源:数据中心)

  4. Authorization Server (认证服务器)

3.2 OAuth2.0基本流程


    步骤详解:

  1. Authorization Request, 第三方请求用户受权

  2. Authorization Grant,用户赞成受权后,会从服务方获取一次性用户受权凭据(如code码)给第三方

  3. Authorization Grant,第三方会把受权凭据以及服务方给它的的身份凭据(如AppId)一块儿交给服务方的向认证服务器申请访问令牌

  4. Access Token,认证服务器核对受权凭据等信息,确认无误后,向第三方发送访问令牌Access Token等信息

  5. Access Token,经过这个Access TokenResource Server索要数据

  6. Protected Resource,资源服务器使用令牌向认证服务器确认令牌的正确性,确认无误后提供资源

    这样服务方,一能够肯定第三方获得了用户对这次服务的受权(根据用户受权凭据),二能够肯定第三方的身份是能够信任的(根据身份凭据),因此,最终的结果就是,第三方顺利地从服务方获取到了这次所请求的服务
    从上面的流程中能够看出,
OAuth2.0完整地解决了用户服务方第三方 在某次服务时这三者之间的信任问题

4、第三方客户端受权码模式详解

4.1 受权码模式

    客户端必须获得用户的受权(authorization grant),才能得到令牌(access token)。OAuth 2.0定义了四种受权方式:

  1. 受权码模式(authorization code

  2. 简化模式(implicit

  3. 密码模式(resource owner password credentials

  4. 客户端模式(client credentials

    受权码模式(authorization code)是功能最完整、流程最严密的受权模式。它的特色就是经过客户端的后台服务器与"服务提供商"的认证服务器进行互动。

4.2 受权码流程图及步骤

    


    它的步骤以下:

  1. 用户访问客户端,后者将前者导向认证服务器

  2. 用户选择是否给予客户端受权

  3. 假设用户给予受权,认证服务器将用户导向客户端事先指定的重定向URI,同时附上一个受权码

  4. 客户端收到受权码,附上早先的重定向URI,向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见

  5. 认证服务器核对了受权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)等

4.3 步骤详情及所需参数

4.3.1 步骤1: 客户端申请认证的URI

    包含如下参数:

  • response_type:表示受权类型,必选项,此处的值固定为"code"

  • client_id:表示客户端的ID,必选项。(如微信受权登陆,此ID是APPID

  • redirect_uri:表示重定向URI,可选项

  • scope:表示申请的权限范围,可选项 state:表示客户端的当前状态,能够指定任意值,认证服务器会原封不动地返回这个值

    示例:

GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
HTTP/1.1 Host: server.example.com

    对比网站应用微信登陆:请求CODE

https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

4.3.2 步骤3:认证服务器回应客户端的URI

    包含如下参数:

  • code:表示受权码,必选项。该码的有效期应该很短,一般设为10分钟,客户端只能使用该码一次,不然会被受权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。

  • state:若是客户端的请求中包含这个参数,认证服务器的回应也必须如出一辙包含这个参数。

    示例:

HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
&state=xyz

4.3.3 步骤4:客户端向认证服务器申请令牌的HTTP请求

    包含如下参数:

  • grant_type:表示使用的受权模式,必选项,此处的值固定为"authorization_code"。

  • code:表示上一步得到的受权码,必选项。

  • redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。

  • client_id:表示客户端ID,必选项。

    示例:

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

    对比网站应用微信登陆:经过code获取access_token

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

4.3.4 步骤5:认证服务器发送的HTTP回复

    包含如下参数:

  • access_token:表示访问令牌,必选项。

  • token_type:表示令牌类型,该值大小写不敏感,必选项,能够是bearer类型或mac类型。

  • expires_in:表示过时时间,单位为秒。若是省略该参数,必须其余方式设置过时时间。

  • refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。

  • scope:表示权限范围,若是与客户端申请的范围一致,此项可省略。

    示例:

 HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

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

    从上面代码能够看到,相关参数使用JSON格式发送(Content-Type: application/json)。此外,HTTP头信息中明确指定不得缓存。

    对比网站应用微信登陆:返回样例

{ 
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

4.4 更新令牌


    若是用户访问的时候,客户端的访问令牌access_token已通过期,则须要使用更新令牌refresh_token申请一个新的访问令牌。
    客户端发出更新令牌的HTTP请求,包含如下参数:

  • granttype:表示使用的受权模式,此处的值固定为"refreshtoken",必选项。

  • refresh_token:表示早前收到的更新令牌,必选项。

  • scope:表示申请的受权范围,不能够超出上一次申请的范围,若是省略该参数,则表示与上一次一致。

    示例:

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA

微信刷新Token:

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

(完)

参考文档一:理解OAuth 2.0
参考文档二:Oauth2.0原理
OAuth 受权的工做原理是怎样的?足够安全吗?

喜欢,在看

本文分享自微信公众号 - JAVA乐园(happyhuangjinjin88)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索