SpringBootSecurity学习(19)前后端分离版之OAuth2.0 token的存储和管理
内存中存储token
我们来继续授权服务代码的下一个优化。现在授权服务中,token的存储是存储在内存中的,我们使用的是 InMemoryTokenStore :

图中的tokenStore方法支持很多种令牌的存储方式,来看一下:
InMemoryTokenStore:这个版本的实现是被默认采用的,它可以完美的工作在单服务器上(即访问并发量压力不大的情况下,并且它在失败的时候不会进行备份),大多数的项目都可以使用这个版本的实现来进行尝试,你可以在开发的时候使用它来进行管理,因为不会被保存到磁盘中,所以更易于调试。
JwtTokenStore:这个版本的全称是 JSON Web Token(JWT),它可以把令牌相关的数据进行编码(因此对于后端服务来说,它不需要进行存储,这将是一个重大优势),但是它有一个缺点,那就是撤销一个已经授权令牌将会非常困难,所以它通常用来处理一个生命周期较短的令牌以及撤销刷新令牌(refresh_token)。另外一个缺点就是这个令牌占用的空间会比较大,如果你加入了比较多用户凭证信息。JwtTokenStore 不会保存任何数据,但是它在转换令牌值以及授权信息方面与 DefaultTokenServices 所扮演的角色是一样的。
JdbcTokenStore:这是一个基于JDBC的实现,令牌会被保存进关系型数据库。使用这个实现时,你可以在不同的服务器之间共享令牌信息,使用的时候请注意把"spring-jdbc"这个依赖加入到你的classpath当中。
RedisTokenStore : 这是一个基于Redis的实现,令牌会被保Redis缓存中。使用这个实现时,你可以在不同的服务器之间共享令牌信息,使用的时候请注意把redis依赖加入到你的classpath当中。关于redis和数据库存储数据有什么不同和需要注意的地方,这里不再描述。
默认的 InMemoryTokenStore 方式存储也是可以进行查询和删除的,我们来看一下,首先将 InMemoryTokenStore 配置为一个bean:

然后配置时调用这个bean:

我们来看一下 InMemoryTokenStore 类中对token有哪些操作:

从方法的名字可以看出,对token的增删改查操作基本都是齐全的,我们来写两个方法查询和删除token:

类中注入的InMemoryTokenStore正是前面定义的bean,只有这样才能操作内存中的token,下面来看一下测试,先根据前面的流程,申请到令牌,然后查询令牌:

然后测试删除令牌:

然后再根据令牌查询受保护的资源,可以发现无法访问了。
使用内存的方式虽然基本的功能都在,但是缺点上面也提到了,就是只能工作在单服务器上面,无法默认实现token共享,另外测试环境使用内存存储也是比较好的选择。
Redis存储token
令牌除了可以存储在内存中,还可以存储在公共的地方,比如redis中,这样单服务器数据不同步的问题可以解决。存储在redis中首先要引入依赖:

然后配置数据源:

然后修改授权配置类,配置redis存储的bean:

这样redis存储token的配置基本就完成了,然后仿照前面的内存存储操作,写两个接口用来查询和删除redis中的token:

启动项目,按照之前的流程获取令牌,访问保护资源,然后查看redis,可以看到里面存储了我们获取的令牌:

来看查询token接口的效果:

来看删除token接口的效果:

删除后,redis中的token也删除了:

只剩下三个刷新的key。
JDBC存储token
使用jdbc存储token的方式也可以做到token共享,操作类是 JdbcTokenStore ,我们来看一下这个类:

类中定义了好多默认操作的sql语句,总共涉及到两张表:oauth_access_token和oauth_refresh_token(如果客户端的grant_type不支持refresh_token,则不会使用该表),来看一下 oauth_access_token 表的结构:
token_id:该字段的值是将access_token的值通过MD5加密后存储的
token:存储将OAuth2AccessToken.java对象序列化后的二进制数据, 是真实的AccessToken的数据值
authentication_id:该字段具有唯一性, 其值是根据当前的username(如果有),client_id与scope通过MD5加密生成的. 具体实现请参考DefaultAuthenticationKeyGenerator.java类
user_name:登录时的用户名, 若客户端没有用户名(如grant_type="client_credentials"),则该值等于client_id
client_id:你懂得
authentication:存储将OAuth2Authentication.java对象序列化后的二进制数据
refresh_token :该字段的值是将refresh_token的值通过MD5加密后存储的
来看一下 oauth_refresh_token 表的字段结构:
token_id:该字段的值是将refresh_token的值通过MD5加密后存储的.
token:存储将OAuth2RefreshToken.java对象序列化后的二进制数据.
authentication:存储将OAuth2Authentication.java对象序列化后的二进制数据
在数据库中创建这两张表:


然后在pom中引入jdbc依赖,在配置文件中配置数据源,此处不再演示。下一步修改授权配置类:

最后仿照前面,写两个查询和删除token的接口:

使用数据库存储token,比前面两种方式多了很多方法和操作,来看 JdbcTokenStore 类:

除了增删改查的操作多了几个方法,包括sql语句的默认写法也有覆盖的set方法。下面来测试,首先按照前面的流程获取token令牌,然后查询数据库:


可以看到数据库中多了两条token数据,看一下查询token接口:

删除接口:

看一下删除接口调用的方法源码:

只是删除了令牌,更新token的记录还会保留。
代码地址: https://gitee.com/blueses/spring-boot-security 23 24
本文由博客一文多发平台 OpenWrite 发布!
SpringBootSecurity学习(19)前后端分离版之OAuth2.0 token的存储和管理的更多相关文章
- SpringBootSecurity学习(15)前后端分离版之 OAuth2.0简单示例
OAuth2.0 OAuth 引入了一个授权层,用来分离两种不同的角色:客户端和资源所有者.客户端来申请资源,资源所有者同意以后,资源服务器可以向客户端颁发令牌.客户端通过令牌,去请求数据.也就是说, ...
- SpringBootSecurity学习(14)前后端分离版之 OAuth2.0介绍
登录总结 前面基本介绍了security的常规用法,同时介绍了JWT和它的一个简单实现,基本上开发中遇到的登录问题都能解决了,即使在分布式开发,或者微服务开发中实现登录也基本没有问题了.securit ...
- SpringBootSecurity学习(16)前后端分离版之 OAuth2.0 加密配置
示例代码的改进 前面使用spring cloud security和spring cloud oauth2写了一个第三方授权的例子,例子非常的简单,主要目的是用来熟悉OAuth2.0 申请授权的整个流 ...
- SpringBootSecurity学习(17)前后端分离版之 OAuth2.0 数据库(JDBC)存储客户端
自动批准授权码 前面我们授权的流程中,第一步获取授权码的时候,都会经历一个授权是否同意页面: 这个流程就像第三方登录成功后,提问是否允许获取昵称和头像信息的页面一样,这个过程其实是可以自动同意的,需要 ...
- SpringBootSecurity学习(23)前后端分离版之OAuth2.0 其它模式
密码模式 前面介绍了授权码模式和刷新令牌两种获取最新令牌的方法,下面来看一下其它模式.首先看密码模式,我们默认配置的三种模式中其实就包含密码模式的支持: 因此我们启动项目,直接使用密码模式即可,访问地 ...
- SpringBootSecurity学习(20)前后端分离版之OAuth2.0刷新token
刷新token 前面的例子和配置都是从头开始申请授权码和令牌,现在来看一下如何根据获取令牌时,回参中的 refresh_token 来刷新令牌.现在在项目中配置的是内存模式的默认用户名密码,第一步先改 ...
- SpringBootSecurity学习(21)前后端分离版之OAuth2.0非对称加密
JWT转换器 前面的例子中,都是在授权服务配置类中配置了一个很简单的jwt转换器,如下: 可以看到我们只用setSigningKey方法配置了一个秘钥,这里使用的是简单的对称加密的方式来加密jwt内容 ...
- SpringBootSecurity学习(22)前后端分离版之OAuth2.0自定义授权码
使用JDBC维护授权码 前面的代码中,测试流程第一步都是获取授权码,然后再携带授权码去申请令牌,授权码示例如下: 产生的授权码默认是 6 位的,产生以后并没有做任何管理,可以说是一个临时性的授权码,o ...
- SpringBootSecurity学习(24)前后端分离版之OAuth2.0 应用登记
应用登记 一个应用要求 OAuth 授权,必须先到对方网站登记,让对方知道是谁在请求.举个例子,下面是github的登记页面: https://github.com/settings/applicat ...
随机推荐
- CodeForces 1058 F Putting Boxes Together 树状数组,带权中位数
Putting Boxes Together 题意: 现在有n个物品,第i个物品他的位置在a[i],他的重量为w[i].每一个物品移动一步的代价为他的w[i].目前有2种操作: 1. x y 将第x的 ...
- CH 5101 最长公共上升子序列
题目传送门 题解:F[i][j] 表示 对于第一个数列枚举到i来说, 第二个数列以j结尾的最大长度是多少. 那么对于更新 F[i] -> F[i+1]来说 如果 a[i+1] == b[j] ...
- poj 3468 A Simple Problem with Integers(原来是一道简单的线段树区间修改用来练练splay)
题目链接:http://poj.org/problem?id=3468 题解:splay功能比线段树强大当然代价就是有些操作比线段树慢,这题用splay实现的比线段树慢上一倍.线段树用lazy标记差不 ...
- codeforces 361 C. Levko and Array Recovery(暴力+思维)
题目链接:http://codeforces.com/contest/361/problem/C 题意:对一个数列有这么两个操作 1.(1,l,r,p)..将区间[l,r]所有数都加上p 2.(2,l ...
- Unsolved输入格式错误1022
https://pintia.cn/problem-sets/994805342720868352/problems/994805480801550336
- CSS3 04. 伸缩布局、设置主轴,侧轴方向、主/侧轴对齐方式、 伸缩比例、元素换行、换行控制、覆盖父元素的align-items;控制子元素顺序、web字体、突变字体
CSS3 在布局方面做了非常大的改进,对块级元素的布局排列变得十分灵活,适应性非常强,其强大的伸缩性,在响应式开发中可以发挥极大的作用.(兼容性不好) 必要元素: 指定一个盒子为伸缩盒子 displa ...
- 聚焦Python分布式爬虫必学框架Scrapy 打造搜索引擎视频教程
下载链接:https://www.yinxiangit.com/595.html 目录: 第1章 课程介绍介绍课程目标.通过课程能学习到的内容.和系统开发前需要具备的知识 第2章 windows下搭建 ...
- FreeSql (十)更新数据
FreeSql支持丰富的更新数据方法,支持单条或批量更新,在特定的数据库执行还可以返回更新后的记录值. var connstr = "Data Source=127.0.0.1;Port=3 ...
- .Ajax(async异步与sync同步)
异步,不会阻碍代码的执行,它会等待所有的同步代码执行完毕后,再执行输出自己的同步结果.(原生js中,只有定时器,DOM,ajax三个东西是异步的.) 同步,代码只会从上到下依次执行,只要一步出错,接下 ...
- Unity3D_07_日志、文本打印
1.Debug.Log(“hello”); 2.打开控制台查看日志:ctrl+shift+c 3.输出一个位置的坐标(需要转换成字符串.ToString()) Vector3 worldPositio ...