一切福田,不離方寸,從心而覓,感無不通。

OAuth2.0四种授权模式及实战

OAuth2.0四种授权模式以及Oauth2.0实战

首先我们得了解什么是Oauth2.0,简单来说Oauth2.0它是一个授权协议。我们可能会听说过,使用Oauth2.0来实现单点登录SSO,以及第三方登录。那个什么是授权?

举个通俗易懂的例子,就是第三方人员A要想进入B公司的大厦进行业务交流的时候,因为A并不是B公司的员工,出于安全的缘故,所以他不能够自由的出入B公司的大厦。那个A到了B公司前台的时候,A得去前台和B公司前台工作人员说明来意,并且出示邀请(访问)证明,此时B公司前台工作人员就会给你一张临时工牌让你进入大厦。

在这个例子当中,A没有工牌所以是无法进入B公司大厦里进行业务交流,B公司前台给A一张临时工牌,这个操作就相当于授权。

总的来说,OAuth 2.0 这种授权协议,就是保证第三方(软件)只有在获得授权之后,才可以进一步访问授权者的数据。

1、Oauth2.0授权许可机制协议

Oauth2.0具有多种授权许可机制协议:授权码许可机制、客户端凭据机制、资源拥有者凭据机制(密码模式)和隐式许可机制。

在了解授权许可机制协议之前,我们得需要了解在OAuth 2.0 的体系里面有 4 种角色,按照官方的称呼它们分别是资源拥有者、客户端、授权服务和受保护资源。

  • 资源拥有者(可以指拥有资源的用户)
  • 客户端(可以理解为第三方系统/软件)
  • 授权服务(权限校验和授权系统(认证服务中心))
  • 受保护资源(用户在系统上所具有的资源/或者能够访问的资源)

1.1、授权码许可机制

授权码许可机制的参与者:资源拥有者、客户端、授权服务、受保护资源

授权码模式这种场景下的授权,第三方软件可以通过拿到资源拥有者授权后的授权码,以及注册时的 client_id 和 client_secret 来换回访问令牌 token 的值。

时序图:
在这里插入图片描述

按照上述时序图举个简单的例子,小明使用微信授权方式登录app。

  1. 小明点开手机里面的app,他不想手动输入账号密码登录,而是采用了微信登录。
  2. 点击微信登录按钮,app拉起授权页面。
  3. 微信授权服务器则生成授权页面,用户看见授权页面点击确定按钮进行授权。
  4. 微信授权服务器校验用户身份合法性后生成请求code,点击确认授权后,页面跳转至app页面并携带请求code(授权码)。
  5. app拿到授权码后,携带授权码向授权服务器获取访问令牌access_token。
  6. 拿到access_token后,则携带access_token向受保护资源发起访问。
  7. 校验access_token无误后,受保护资源返回资源数据(个人的身份数据,昵称,地区等信息)。
  8. 成功登录app,小明继续使用app内的功能。
1.1.1、为什么需要生成授权码以及根据授权码获取access_token步骤?

假设从时序图中抹除授权码的流程,那么从第三步,用户点击确定授权,此时资源拥有者与授权服务器就建立起关联,此时,资源拥有者则与第三方软件前端断开关联,界面则会停留在授权界面。然后授权服务器直接把access_token送给第三方软件后端,后端在携带access_token去访问受保护资源。虽然说资源数据已经拿到了,但是如何通知用户呢?因此,得需要建立起用户与第三方软件前端的关联,所以授权服务器生成授权码后重定向到第三方软件前端则是重新建立起用户与第三方软件前端的关联。

既然如此,那么为什么授权服务器不直接重定向传回access_token,首先并不能保证重定向采用的形式是否是https,而且并不是所有的客户端都支持https,所以重定向传回access_token就会增加access_token失窃的风险。虽然access_token需要与client_id,client_secret一起才能够通过授权服务器校验访问到保护资源,但是在安全层面来说,这都是不适合的。在此层面上看,授权码的作用在于access_token不经过用户浏览器, 保护了access_token。

1.1.2、授权码code可以暴露?

1、授权码Authentication code只能用一次,而且会很快超时失效, 使得被截获后难以运用。

2、授权码需要和client id/client secret共同完成认证,才能够获得access_token。就算授权码如果失窃,单凭授权码是无法得到access_token的。

1.1.3、access_token不能暴露在浏览器那么该存放在哪?

重定向传回access_token会使安全保密性要求极高的访问令牌暴露在浏览器,增加访问令牌失窃风险。

刚开始接触Oauth2.0的我也是比较迷,既然access_token不能暴露在浏览器,那么我到底将access_token存放在哪呢?那我前端有如何进行访问那些受保护资源呢?

在我看来,重定向携带的参数在URL上,http协议下重定向传回access_token的形式,是没有经过数据加密的,他会增加令牌失窃的风险。那么关于access_token存放在哪的问题,个人认为通过授权码以及客户端id和secret共同校验后获取的access_token,可以把access_token存放在localStorage中,localStorage虽然是永久存储,但是access_token会有一个有效期,有效期到了之后,即便access_token一直都存在但是有效期过后就无法访问到受保护资源。

1.1.4、sessionStorage和localStorage区别

1、sessionStorage(会话存储)

  • 生命周期:浏览器打开到关闭的过程
  • 大小:5M
  • 保存的位置:浏览器端

 

2、localStorage(本地存储【永久存储】)

  • 生命周期: 永久,只能人为删除
  • 大小: 5M甚至更大
  • 保存的位置: 浏览器端

 

**注意: **不同浏览器无法共享localStorage或sessionStorage中的信息。相同浏览器的不同页面间【相同域名和端口】可以共享相同的 localStorage,但是不同页面或标签页间无法共享sessionStorage的信息。

1.2、资源拥有者凭据机制(密码模式)

客户端凭据机制的参与者:资源拥有者、客户端、授权服务、受保护资源

资源拥有者凭据,顾名思义就是资源拥有者的凭据(账号,密码)。在这场景里面就不存在第三方软件这概念,相当于就是访问系统中的一个子系统,他们之间互相信任。举个例子来说就是,腾讯有许多的游戏,你只需要用qq账号密码就可以登录游戏玩,不需要进行腾讯授权。因为该游戏是腾讯旗下的,他们相互信任的,所以不存在第三方的说法。

时序图:
在这里插入图片描述

1.3、客户端凭据机制

客户端凭据机制的参与者:客户端、授权服务、受保护资源

相当于就是第三方软件访问不需要资源拥有者授权的资源和数据,换句话说在这里客户端也可以看作是资源拥有者。举个例子来说就是第三方软件访问一些公共的服务,譬如说一些地图信息,logo图标等。

这种场景下的授权,便是客户端凭据许可,第三方软件可以直接使用注册时的 client_id 和 client_secret 来换回访问令牌 token 的值。

时序图:
在这里插入图片描述

1.4、隐式许可机制

隐式许可机制的场景适用于没有后端服务的应用,举个例子来说的话就是在浏览器中执行,譬如说JavaScript应用。

在这种情况下,第三方软件对于浏览器就没有任何保密的数据可以隐藏了,也不再需要应用密钥 app_secret 的值了,也不用再通过授权码 code 来换取访问令牌 access_token 的值了。因此,隐式许可授权流程的安全性会降低很多。

这种场景下的授权,第三方软件可以直接使用注册时的 client_id来换回访问令牌 token 的值。

时序图:
在这里插入图片描述

2、Oauth2.0实战

2.1、搭建授权服务器

2.1.1、 AuthorizationServerConfig(授权服务器配置)

完成以下三个配置:

  • ClientDetailsServiceConfigurer:用来配置客户端详情服务(ClientDetailsService)【客户端详情信息在这里进行初始化,你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息。】
  • AuthorizationServerEndpointsConfigurer:用来配置令牌(token)的访问端点和令牌服务(tokenservices)
  • AuthorizationServerSecurityConfigurer:用来配置令牌端点的安全约束.

配置客户端详情:

 

AuthorizationServerSecurityConfigurer:用来配置令牌端点的安全约束.

 

AuthorizationServerEndpointsConfigurer:用来配置令牌(token)的访问端点和令牌服务(tokenservices)

 

自定义token增强器:EnhanceTokenEnhancer

 

2.1.2、spring security配置

 

2.1.3、四种许可机制测试

启动授权服务器验证四种授权模式的场景。

1、隐式许可机制

首先在浏览器中发送请求

 

在这里插入图片描述
回车后,需要登陆授权
在这里插入图片描述
点击登陆后
在这里插入图片描述
则可以直接获取到access_token

 

2、客户端凭据机制

使用postman发送请求

 

在这里插入图片描述

3、资源拥有者凭据机制(密码模式)

使用postman发送请求

 

在这里插入图片描述

4、授权码许可机制

打开浏览器访问

 

点击登陆,并授权
在这里插入图片描述
在这里插入图片描述
获取授权码

 

在这里插入图片描述
使用postman测试发送请求获取access_token

 

在这里插入图片描述

2.2、搭建客户端

2.2.1 OAuth2Client客户端配置

OAuthClientConfig客户端配置

 

2.2.2 spring security配置

 

2.2.3 场景模拟DemoController

 

2.3、搭建资源服务器

2.3.1 资源服务器配置

 

2.3.2 受保护资源UserController

 

2.4、 模拟测试

2.4.1 postman模拟客户端访问受保护资源

使用torlesse用户拿到token,然后使用postman模拟客户端访问受保护资源
在这里插入图片描述
postman作为模拟客户端,模拟访问受保护资源

 

在这里插入图片描述

2.4.2客户端访问受保护资源

浏览器访问:http://localhost:8083/torlesse/demo/remoteCall
在这里插入图片描述
点击登录
在这里插入图片描述
访问到受保护资源演示成功。

2.4.3演示单点登录
准备工作

1)启动两个客户端 端口分别问8082 8083

1.1、修改客户端配置文件application.yml

 

1.2、配置多个客户端
在这里插入图片描述
VM options设置:-DPORT=8082
在这里插入图片描述
启动
在这里插入图片描述

单点登录验证

浏览器访问:http://localhost:8083/torlesse/demo/userInfoPage
在这里插入图片描述
点击登录
在这里插入图片描述
浏览器访问:http://localhost:8082/torlesse/demo/userInfoPage
在这里插入图片描述
单点登录演示成功。

2.5、自定义授权模式

Oauth2.0具有多种授权许可机制协议:授权码许可机制、客户端凭据机制、资源拥有者凭据机制(密码模式)和隐式许可机制。

在源码中即可看到四种模式的实现类,还有一个RefreshTokenGranter则是刷新令牌,用于access_token失效时刷新过期时间。
在这里插入图片描述
假如现在我需要实现手机验证码登录或者微信扫码登录等功能的时候,我们该如何处理呢?

我们可以继承AbstractTokenGranter实现自定义授权模式。

手机短信验证码模式如下:

2.5.1 继承AbstractTokenGranter类, 实现手机验证码自定义模式

 

手机验证码token

 

2.5.2 授权服务器配置修改

AuthorizationServerConfig授权服务器配置类中添加TokenGranter

 

修改AuthorizationServer配置令牌访问端点,添加以下内容
在这里插入图片描述

 

2.5.3 手机号验证码授权模式验证演示

postman模拟客户端发送请求

 

在这里插入图片描述
项目访问地址Github:github
项目访问地址Gitee:gitee

书籍推荐

以下是一些关于OAuth2.0的书籍推荐及其理由:

  1. 《OAuth 2实战》:本书深入探讨OAuth的运行机制,详细介绍如何在不安全的网络环境下正确使用、部署OAuth,确保安全认证,是目前关于OAuth最全面深入的参考资料。
  2. 《OAuth 2权威指南》:本书是一本全面而深入地介绍OAuth2.0的书籍。它涵盖了从基础知识到高级主题的所有内容,并提供了大量示例和代码。
  3. 《Mastering OAuth 2.0》:本书从客户的角度提供了OAuth 2.0协议的深入观点。注重实用性和安全性。本书探讨了客户端与OAuth 2.0服务提供者集成的各种方式。在此过程中,讨论一些注意事项和最佳实践。

 

from:https://blog.csdn.net/NeverFG/article/details/131405161