spring cloud实战与思考(四) JWT之Token主动失效
需求:
JWT泄露、密码重置等场景下,需要将未过期但是已经不安全的JWT主动失效。
本文不再复述JWT的基础知识,不了解的小伙伴可以自行Google一下。这里主要是针对以上需求聊一聊解决方案。如果服务端发给客户端的JWT还在有效期内,但是变得不安全,服务端需要及时将这些JWT标识出来并作废掉。相较于session机制,服务端对JWT的控制要弱很多。JWT一旦签发,就脱离了服务端的掌控。通常情况下,服务端只能通过设置JWT的过期时间“exp”声明,使得JWT在过期后被动失效。
正所谓鱼与熊掌不可兼得。在我们享受JWT便利性的同时,也要设计复杂点的机制来弥补服务器对JWT控制能力弱的缺点。网上有人建议服务器将签发的JWT都存一份到分布式缓存中,这样JWT就能被跟踪和标识。这种方式虽然解决了问题,但是每个JWT都保存起来,每次校验都做查询的方式同分布式session几乎无分别。这相当于放弃了JWT占用服务器空间小、有效性校验速度快的优点。在没有跨域资源访问的需求场景下,分布式session的方案反而更有优势,至少可以在session中保存敏感信息,而不用担心在客户端被泄露。
下面讲一下我在当前项目中使用的JWT控制方案:
1. 每个JWT必须设置过期时间,并且该时间不要设置的过长。
2. 在用户登陆表中,为每个用户分配一个“token_group_id”字段。该字段保存一个随机字符串。

3. 在JWT的payload中增加“groupId”声明。签发JWT的时候,将用户对应的“token_group_id”字符串写入该声明。
{
"exp": 1525256018000,
"groupId": "jeJ4IVpR17z68Q0cTr53gQ25e588P653"
}
4. 在服务端的分布式缓存上保存一个“groupId”黑名单列表。如果用户的JWT泄露或者重置密码等需要作废已经签发给用户的JWT时,为该用户生成一个新的“token_group_id”存入用户登陆表。将原有的“token_group_id”加入黑名单。
5. “token_group_id”在黑名单中的保存时间是JWT的过期时间。过期后“token_group_id”自动从黑名单中删除。
6. 所有需要做JWT有效性校验的服务器启动时访问分布式缓存将黑名单下载到本地内存。并且订阅分布式缓存的消息推送功能,在黑名单发生增删的时候,接收推送消息同步修改内存中的黑名单列表。
7. 服务器做JWT校验的时候,除了校验过期时间,还要查询内存中的黑名单列表。若JWT的“groupId”在黑名单中,则判定该JWT为失效。
讨论:
1. 你这个方案也用到了分布式缓存,也要在缓存中保存数据。这和分布式session或者保存所有的JWT的方案性质不是一样的吗?
形式上虽然相同,但是保存数据的数量级差别很大。其它两种方案需要保存当前活动用户的全集,而本方案只保存不安全的JWT。相信通常情况下出现token泄露和密码重置的频率是比较低的。需要撤销的JWT占整个活动用户的百分比很小。
此外JWT只在黑名单中保存一个过期周期,此后就会被删除,进一步控制了黑名单的增长。这样黑名单就可以装载到服务器的内存中,协助完成JWT的本地校验。而无需每次校验时要访问远端服务。
2. 为什么多此一举的新增一个“groupId”,直接将需要作废的JWT放到黑名单中不就行了吗?
1) JWT本身比较长,使用较短的“groupId”可以加快黑名单的查询速度。
2) 若系统不限制用户同一时间能申请的JWT数量。那么可能遇到用户在短时间内恶意请求大量Token的情况。这些Token都放到黑名单中会导致黑名单数量迅速膨胀。使用“groupId”则可以避免这种不可控情况。
3. 你这个方案又要分布式缓存,又要做黑名单的实时同步。整个方案实施的复杂性似乎超过了分布式session,用它代替分布式session会不会得不偿失?
1)在一个稍具规模的分布式系统中,分布式缓存、系统总线都是必备的组件。利用这些现有组件可以设计多种方案做数据同步。所以方案看似复杂,实现起来还是不难的。
2)每个系统侧重的性能指标各有不同。本方案的JWT校验的计算和查询都是在本地内存中完成,不需要依赖远端服务。能够缩短请求的响应时间。对于强调低延迟响应的系统还是比较合适的。
spring cloud实战与思考(四) JWT之Token主动失效的更多相关文章
- spring cloud实战与思考(二) 微服务之间通过fiegn上传一组文件(上)
需求场景: 微服务之间调用接口一次性上传多个文件. 上传文件的同时附带其他参数. 多个文件能有效的区分开,以便进行不同处理. Spring cloud的微服务之间接口调用使用Feign.原装的Feig ...
- spring cloud实战与思考(一) spring config全局配置方案设计
“spring cloud”的配置中心工具“spring cloud config”提供了分布式系统配置文件集中管理解决方案.该工具功能强大,实现也很简单.网上可以搜索到很多开发教程和用例.本文并不是 ...
- spring cloud实战与思考(五) JWT之携带敏感信息
需求: 需要将一些敏感信息保存在JWT中,以便提高业务处理效率. 众所周知JWT协议RFC7519使用Base64Url对Header和Payload的Json字符串进行编解码.A JWT is re ...
- spring cloud实战与思考(三) 微服务之间通过fiegn上传一组文件(下)
需求场景: 用户调用微服务1的接口上传一组图片和对应的描述信息.微服务1处理后,再将这组图片上传给微服务2进行处理.各个微服务能区分开不同的图片进行不同处理. 上一篇博客已经讨论了在微服务之间传递一组 ...
- [Spring Cloud实战 | 第六篇:Spring Cloud Gateway+Spring Security OAuth2+JWT实现微服务统一认证授权
一. 前言 本篇实战案例基于 youlai-mall 项目.项目使用的是当前主流和最新版本的技术和解决方案,自己不会太多华丽的言辞去描述,只希望能勾起大家对编程的一点喜欢.所以有兴趣的朋友可以进入 g ...
- Spring Cloud实战 | 最终篇:Spring Cloud Gateway+Spring Security OAuth2集成统一认证授权平台下实现注销使JWT失效方案
一. 前言 在上一篇文章介绍 youlai-mall 项目中,通过整合Spring Cloud Gateway.Spring Security OAuth2.JWT等技术实现了微服务下统一认证授权平台 ...
- Spring Cloud实战 | 最八篇:Spring Cloud +Spring Security OAuth2+ Axios前后端分离模式下无感刷新实现JWT续期
一. 前言 记得上一篇Spring Cloud的文章关于如何使JWT失效进行了理论结合代码实践的说明,想当然的以为那篇会是基于Spring Cloud统一认证架构系列的最终篇.但关于JWT另外还有一个 ...
- Spring Cloud实战之初级入门(四)— 利用Hystrix实现服务熔断与服务监控
目录 1.环境介绍 2.服务监控 2.1 加入依赖 2.2 修改配置文件 2.3 修改启动文件 2.4 监控服务 2.5 小结 3. 利用hystrix实现消费服务熔断 3.1 加入服务熔断 3.2 ...
- Spring Cloud实战 | 第九篇:Spring Cloud整合Spring Security OAuth2认证服务器统一认证自定义异常处理
本文完整代码下载点击 一. 前言 相信了解过我或者看过我之前的系列文章应该多少知道点我写这些文章包括创建 有来商城youlai-mall 这个项目的目的,想给那些真的想提升自己或者迷茫的人(包括自己- ...
随机推荐
- 【Codeforces Round 725】Canada Cup 2016
模拟Canada Cup 2016,ABC三题,Rank1376 第三题卡住了 Codeforces 725 C 求出两个相同字符的位置,记为x和y. 然后考虑把相同的那个字符放在第一行的什么地方, ...
- 【Codeforces Round 1120】Technocup 2019 Final Round (Div. 1)
Codeforces Round 1120 这场比赛做了\(A\).\(C\)两题,排名\(73\). \(A\)题其实过的有点莫名其妙...就是我感觉好像能找到一个反例(现在发现我的算法是对的... ...
- try--catch--finally中return返回值执行的顺序
1.try块中没有抛出异常,try.catch和finally块中都有return语句 public static int NoException(){ int i=10; try{ System.o ...
- c# 获取文件本身的哈希值
1. 哈希值是什么 我个人认为,哈希值是一个统称,也就是经过加密算法后得出的长度较短.位数固定的输出序列即散列值,这个哈希值是一个凭证,一个数字签名之类的,唯一对应你加密之前的东西,这都是我自个儿觉得 ...
- JavaWeb开发中采用FreeMarker生成Excel表格
最近做了一个需求,要求导出一个采购合同的Excel表格,这个表格样式比较多.由于是合同,这个Excel表格里面有好多格式要求,比如结尾处签字那部分就有格式要求.这里介绍种采用FreeM ...
- java内存模型与volatile变量与Atomic的compareAndSet
java分主内存和工作内存, 主内存是线程共享的, 工作内存是每个线程独有的. java对主内存的操作是通过工作内存间接完成的: 先拷贝主内存变量值到工作内存, 在工作内存操作这个变量的副本, 完成后 ...
- NOIp2014提高组初赛错题简析
总体分析 \(89pts\),粗略来看选择题错的比较多,\(-6pts\).同时又是尿性的填空杀扣了\(5pts\). 不过后面的两大题全对了还是可喜可贺 错题精析 单项选择T8 编译器的主要功能是( ...
- iOS开发简记(2):自定义tabbar
tabbar是放在APP底部的控件.常见的APP都使用tabbar来进行功能分类的管理,比如微信.QQ等等. 小程需要一个特殊一点的tabbar,要求突显中间的那个按钮,让中间按钮特别显眼,从而引导用 ...
- 自己动手写把”锁”---LockSupport深入浅出
本篇是<自己动手写把"锁">系列技术铺垫的最后一个知识点.本篇主要讲解LockSupport工具类,它用来实现线程的挂起和唤醒. LockSupport是Java6引入 ...
- Docker网络解决方案 - Calico部署记录
简单来说,实现docker跨主机容器间通信,常用的第三方网络方案是Flannel,Weave,Calico:Flannel会为每个host分配一个subnet,容器从这个subnet中分配ip,这些i ...