为了账号安全,请及时绑定邮箱和手机立即绑定

IdentityServer4实战 - 谈谈 JWT Token 的安全策略

标签:
C#

一.前言

众所周知,IdentityServer4 默认支持两种类型的 Token,一种是 Reference Token,一种是 JWT Token 。前者的特点是 Token 的有效与否是由 Token 颁发服务集中化控制的,颁发的时候会持久化 Token,然后每次验证都需要将 Token 传递到颁发服务进行验证,是一种中心化的比较传统的验证方式。JWT Token 的特点与前者相反,每个资源服务不需要每次都要都去颁发服务进行验证 Token 的有效性验证,该 Token 由三部分组成,其中最后一部分包含了一个签名,是在颁发的时候采用非对称加密算法(最新的JWT Token)进行数据签名的,保证了 Token 的不可篡改性,保证了安全,与颁发服务的交互,仅仅是获取公钥用于验证签名,且该公钥获取以后可以自己缓存,持续使用,不用再去交互获得,除非Token包含的 keyid 对应的 公钥没被缓存(新的),就会再次向颁发服务获取。我画了一张流程图,大家可以去查看:https://www.cnblogs.com/stulzq/p/9226059.html

这里说一下我在文章说所说的名词:

颁发服务:即生成Token的服务。

资源服务:提供给用户访问的API资源

二.JWT Token 的安全问题

前言中有过叙述,JWT 类型的 Token 在验证的时候,无需依靠颁发服务来验证 Token 的有效性,是一种去中心化的验证方式,这就意味着颁发服务无法集中控制 Token。假如 Token 暴露以后,在 Token 有效期内,将会一直被人恶意使用,这时候该怎么办呢?这里主要从两个方面来讲,一个是尽量避免被恶意获取Token,一个是被恶意获取了怎么控制失效。请听下面分解。

1.使用 HTTPS

此种方式是避免被人获取恶意获取Token。

HTTPS 在传输数据时,数据内容是加密的,可以有效避免中间人攻击,所以在使用 JWT Token 的程序建议都采用HTTPS。

图片描述

2.添加自定义Token失效机制

此种方式是被恶意获取了怎么控制失效。

因为 IdentityServer4 对 JWT Token,默认是没有控制失效的机制的,所以如果我们想添加这种机制,只有我们自定义,下一节做详细介绍。

三.自定义Token失效机制

图片描述

1.简单黑名单模式

顾名思义,就是添加一个 Token 黑名单,这个黑名单建议存在诸如 Redis 等分布式缓存,数据库等介质,可以让所有资源服务共同访问。不推荐添加在资源服务本地缓存,如果这样做,那么每次添加黑名单还需要同步到每个资源服务。每个资源服务在每次验证Token的时候需要查询一下黑名单,如果在黑名单里面,即 Token 无效。

2.进阶黑名单模式

前面小节的 【简单黑名单模式】 有一个非常大的弊端,就是每个 Token 验证时都需要去验证是否在黑名单,正常情况下,我们正常的Token 是占绝大多数的,如果用此种机制,那么对资源是一种很大的浪费。那么我们需要设立一种机制,来让我们认为 可疑 的Token进行黑名单验证,那么如何来判断Token是否可疑呢,我这里想了一种方式。

如何判断 Token 是否可疑:

我们在生成Token的时候,可以添加自定义 Claim (身份信息单元),那么我们可以参考网站登录的安全机制,那么我们可以添加一个用户ip的Claim,这样我们生成的Token都会携带用户生成Token时的IP,我们每次验证Token是否有效时,就可以根据客户端来源IP与Token携带的IP进行匹配,如果匹配不上,那么该Token我们就可以认为是可疑的,从而进行黑名单的验证。

该方式相对于前面的 【简单黑名单模式】模式算是一个比较好的进阶了。

在这里,我们还需要考虑到IP作为用户的私密信息,我们将IP放入Token时,需要对IP进行加密。因为 JWT Token 前两部分,仅仅是 base64 Encode 而已。

3.强化黑名单模式

无论是【简单黑名单模式】还是【进阶黑名单模式】,我们在对比黑名单时是对token进行完全比对,这样的方式,在某些场景就存在局限性,比我想让该用户在某某时间以前颁发的Token都算作黑名单。所以我们在判断黑名单时可以根据用户id以及token颁发时间来判断。如果让规则自动失效?我们可以用前面设定的 token颁发时间加上我们颁发服务设置的token有效时间就等于规则失效时间。

4.将Token添加进黑名单的方式

我们前面设立了黑名单模式,那么我们的Token何时加入黑名单呢,难道让用户说,我的 Token 被盗了,你把我的 Token加入黑名单吧,这肯定不现实。我们可以在退出登录时,就自动往黑名单添加一条规则,采用【强化黑名单模式】添加用户id以及当前时间作为token颁发时间来验证。比如用户id1000,此用户在 2018-09-20 12:11 退出,我们就可以添加一条规则 userid=1000,tokenissuetime=2018-09-20 12:11 ,该规则表示只要用户id为1000的并且token颁发时间小于2018-09-20 12:11的token,都被算作黑名单token。

这时有人可能会说,这个token如果还是这个用户再次拿来使用,那还是有效的,你这个怎么没让他失效呢?我们设立黑名单模式就是为了避免用户的还在有效期的Token被他人恶意使用。对于用户自己来说,这个问题就无关紧要了。

5.全部 Token 失效的机制。

全部Token失效的方式,目前我想了两种:

1.更换颁发服务的密钥对,并且重启所有资源服务(资源服务获取的公钥默认存在内存,重启可以丢失)。这样原本的Token在验证时,将会找不到对应的公钥,导致验签失败从而Token无效。

2.类似于前面【强化黑名单模式】的验证黑名单的方式,我们可以在验证Token的流程中加两个配置,一个是控制这种配置是否开启的开关,一个是某个时间,规则就是如果在这个时间以前颁发Token全部算作无效Token。这种就需要资源服务支持热加载配置,从而避免重启资源服务。

我个人推荐第二种方式。

四.写在最后

文中所诉是总结了我长久以来的想法,token加入ip还有根据id和颁发时间验证黑名单都是我今天无意间想到的。如果你阅读了本文有什么不明白或者你认为有改进的地方,或者更好的地方,欢迎在评论与我交流。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消