OAuth2.0授权协议+4种认证模式了解

OAuth2介绍

OAuth 2.0是目前最流行的授权机制,用来授权第三方应用,获取用户数据。

OAuth(开放授权)是一个关于授权的开放标准,该标准允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息(比如照片、视频、用户信息等),而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容,OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0。即完全废止了OAuth1.0。OAuth 2.0协议正式发布为RFC-6749。

对于用户而言,我们在互联网应用中最常见的 OAuth 应用就是各种第三方登录,例如 QQ授权登录、微信授权登录、微博授权登录、GitHub 授权登录等。

OAuth2.0中的四个重要角色

OAauth2.0包括的角色 说明
资源拥有者 通常为用户,也可以是应用程序,即该资源的拥有者。
客户端 本身不存储资源,需要通过资源拥有者的授权去请求资源服务器的资源,比如:Android客户端、Web客户端(浏览器端)、微信客户端等。
授权服务器(也称认证服务器) 用于服务提供商对资源拥有者的身份进行认证、对访问资源进行授权,认证成功后会给客户端发放令牌 (access_token),作为客户端访问资源服务器的凭据。
资源服务器 存储资源的服务器。

OAuth2 四种认证模式

1. Authorization Code(授权码模式)

第三方应用先申请一个授权码code,然后通过code获取令牌Access Token

授权码模式是功能最完全,流程最严密安全的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动,access_token不会经过浏览器或移动端的App,而是直接从服务端去交换,这样就最大限度的减小了令牌泄漏的风险

流程:

在这里插入图片描述

说明:

  1. 【步骤1,2】用户访问客户端,需要使用服务提供商的数据(用户信息),客户端通过重定向跳转到服务提供商的页面。
  2. 【步骤3】用户选择是否给予客户端授权访问服务提供商(用户信息)数据的权限。
  3. 【步骤4】用户给与授权。授权系统通过重定向(redirect_uri)并携带 授权凭证(code) 跳转回客户端。
  4. 【步骤5,6】客户端将授权凭证(code)发送给客服端服务器,客户端服务器携带授权码(code)、客户端id(client_id)和秘钥(client_secret)向认证服务器请求访问令牌(access_token)。
  5. 【步骤7,8】认证服务器核对授权码等信息,确认无误后,向客户端服务器发送访问令牌(access_token)和更新令牌(refresh_token),然后客户端服务器再发送给客户端。
  6. 【步骤9,10】客户端持有访问令牌(access_token)和需要请求的参数向客户端服务器发起资源请求,然后客户端服务器再向服务提供商的资源服务器请求资源(web API)。
  7. 【步骤11,12,13】服务提供商的资源服务器返回数据给客户端服务器,然后再回传给客户端使用。

上述流程,只有第二步需要用户手动进行授权,之后的流程都是客户端的后台和认证服务器后台之前进行"静默"操作,对于用户来说是无感知的。

关键步骤:

步骤2:

客户端申请认证的url,包含以下参数:

参数 说明
response_type 授权类型,必选项,此处的值固定为"code"。
client_id 客户端的ID,第三方应用注册的ID,用于身份认证,必选项。
redirect_uri 重定向URI,接受或拒绝请求后的跳转网址,可选项。
scope 申请的权限范围,可选项。
state 客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

示例

A 网站提供一个链接,用户点击后就会跳转到 B 网站,授权用户数据给 A 网站使用。下面就是 A 网站跳转 B 网站的一个示意链接:

https://b.com/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read 

response_type参数表示要求返回授权码(code);

client_id参数让 B 网站知道是谁在请求;

redirect_uri参数是 B 网站接受或拒绝请求后的跳转网址;

scope参数表示要求的授权范围(这里是只读)。

步骤3:

用户跳转后,B 网站会要求用户登录,然后询问是否同意给予 A 网站授权(此过程也可以自动授权,用户无感知)。

步骤4:

服务器回应客户端的url,包含以下参数:

参数 说明
code 授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。
state 如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

示例

在第 2 步骤用户表示同意之后,这时 B 网站就会跳回redirect_uri参数指定的网址。跳转时,会传回一个授权码,就像下面这样。

https://a.com/callback?code=AUTHORIZATION_CODE

步骤6:

客户端向认证服务器申请令牌的HTTP请求,包含以下参数:

参数 说明
client_id 客户端ID,必选项。
client_secret 客户端秘钥,必选项
grant_type 使用的授权模式,必选项,此处的值固定为"authorization_code"。
code 授权码,就是刚刚获取的授权码,必选项。
注意:授权码只使用一次就无效了,需要重新申请。
redirect_uri 重定向URI,必选项,且必须和申请授权码时用的redirect_uri一致。

示例

在第 3 步骤中,A 网站拿到授权码以后,就可以在后端,向 B 网站请求令牌。

https://b.com/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL

client_id参数和client_secret参数用来让 B 确认 A 的身份(client_secret参数是保密的,因此只能在后端发请求);

grant_type参数的值是authorization_code,表示采用的授权方式是授权码;

code参数是上一步拿到的授权码;

redirect_uri参数是令牌颁发后的回调网址。

步骤7:

认证服务器发送的HTTP回复,包含以下参数:

参数 说明
access_token 访问令牌,必选项。
token_type 令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
expires_in 过期时间,单位为秒。如果省略该参数,必须使用其他方式设置过期时间。
refresh_token 更新令牌,用来获取下一次的访问令牌,可选项。
scope 权限范围,如果与客户端申请的范围一致,此项可省略。

示例

第 4 步骤中,B 网站收到请求以后,就会颁发令牌。具体做法是向redirect_uri指定的网址,发送一段 JSON 数据:

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

{
    
    "access_token":"ACCESS_TOKEN","token_type":"bearer","expires_in":2592000,"refresh_token":"REFRESH_TOKEN","scope":"read","uid":100101,"info":{
    
    ...}

上面 JSON 数据中,access_token字段就是令牌,A 网站在后端拿到了。注意:HTTP头信息中明确指定不得缓存。

2. Impliclt Grant(隐式授权模式)

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

流程:

在这里插入图片描述

说明:

  1. 【步骤1,2】用户访问客户端,需要使用服务提供商的数据(用户信息),客户端通过重定向跳转到服务提供商的页面。
  2. 【步骤3】用户选择是否给予客户端授权访问服务提供商(用户信息)数据的权限。
  3. 【步骤4】用户给与授权。授权系统通过重定向(redirect_uri)并携带 访问令牌(access_token)跳转回客户端。
  4. 【步骤5】客户端向资源服务器发出请求资源的请求。
  5. 【步骤6,7】服务提供商的资源服务器返回数据给客户端使用。

关键步骤:

步骤2:

客户端申请认证的url,包含以下参数:

参数 说明
response_type 授权类型,必选项,此处的值固定为"token"。
client_id 客户端的ID,第三方应用注册的ID,用于身份认证,必选项。
redirect_uri 重定向URI,接受或拒绝请求后的跳转网址,可选项。
scope 申请的权限范围,可选项。
state 客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

示例

A 网站提供一个链接,用户点击后就会跳转到 B 网站,授权用户数据给 A 网站使用。下面就是 A 网站跳转 B 网站的一个示意链接:

https://b.com/oauth/authorize?client_id=p2pweb&response_type=token&scope=app&redirect_uri=http://xx.xx/notify

参数描述同授权码模式 ,注意response_type=token,说明是简化模式。

步骤3:

用户跳转后,B 网站会要求用户登录,然后询问是否同意给予 A 网站授权(此过程也可以自动授权,用户无感知)。

步骤4:

授权服务器将授权码将令牌(access_token)以Hash的形式存放在重定向uri的fargment中发送给浏览器。

认证服务器回应客户端的URI,包含以下参数:

参数 说明
access_token 访问令牌,必选项。
token_type 令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
expires_in 过期时间,单位为秒。如果省略该参数,必须使用其他方式设置过期时间。
scope 权限范围,如果与客户端申请的范围一致,此项可省略。
state 如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

示例

https://server.example.com/cb#access_token=ACCESS_TOKEN&state=xyz&token_type=example&expires_in=3600
或
https://a.com/callback#token=ACCESS_TOKEN

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

3. Resource Owner Password Credentials Grant(密码模式)

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

使用用户名/密码作为授权方式从授权服务器上获取令牌,一般不支持刷新令牌。这种方式风险很大,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下

流程:

在这里插入图片描述

说明:

  1. 【步骤1,2】用户向第三方客户端提供,其在服务提供商那里注册的用户名和密码。
  2. 【步骤3】客户端将用户名和密码发给认证服务器,向后者请求访问令牌(access_token)。
  3. 【步骤4】授权认证服务器确认身份无误后,向客户端提供访问令牌(access_token)。
  4. 【步骤5】客户端向资源服务器发出请求资源的请求。
  5. 【步骤6,7】服务提供商的资源服务器返回数据给客户端使用。

关键步骤:

步骤3

客户端拿着资源拥有者的用户名、密码向授权服务器请求令牌(access_token),包含如下参数:

参数 说明
client_id 客户端ID,必选项。
client_secret 客户端秘钥,必选项
grant_type 使用的授权模式,必选项,此处的值固定为"password"。
username 资源拥有者用户名,必选项。
username 资源拥有者密码,必选项。

示例

https://oauth.example.com/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=password&username=USERNAME&password=PASSWORD

发送给 client 这种模式十分简单,但是却意味着直接将用户敏感信息泄漏给了client,因此密码模式一般用于我们自己开发的,第一方原生App或第一方单页面应用。

4. Client Credentials Grant(客户端凭证模式)

指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。

流程:

在这里插入图片描述

说明:

  1. 【步骤1,2】客户端向授权认证服务器进行身份认证,并申请访问令牌(access_token)。
  2. 【步骤3】授权认证服务器验证通过后,向客户端提供访问令牌(access_token)。
  3. 【步骤4】客户端向资源服务器发出请求资源的请求。
  4. 【步骤5,6】服务提供商的资源服务器返回数据给客户端使用。

关键步骤:

步骤2

客户端发出的HTTP请求,包含以下参数:

参数 说明
client_id 客户端ID,必选项。
client_secret 客户端秘钥,必选项
grant_type 使用的授权模式,必选项,此处的值固定为"client_credentials"。

示例

https://oauth.example.com/token?grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET

服务提供者验证通过以后,直接返回令牌。 这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。

因此这就要求我们对client完全的信任,而client本身也是安全的。

因此这种模式一般用来提供给我们完全信任的服务器端服务。比如,合作方系统对接,拉取一组用户信息。

客户端模式适应于没有用户参与的,完全信任的一方或合作方服务器端程序接入。

猜你喜欢

转载自blog.csdn.net/weixin_45559449/article/details/129258158