当前位置:首页 > 问答 > 正文

用Redis集群搭建那个能扛住压力又安全的JWT验证服务,感觉挺靠谱的

“用Redis集群搭建那个能扛住压力又安全的JWT验证服务,感觉挺靠谱的”

这个想法其实挺实在的,就是把JWT和Redis这俩东西捏在一起,取长补短,JWT本身是无状态的,也就是说,服务器发出去这个令牌之后,就不管了,下次用户带着令牌来,服务器只要校验一下签名对不对、过期了没有就行,这好处是服务器轻松,但坏处是也挺要命的:你想让某个令牌立刻失效就办不到了,因为它还在有效期内,签名也是对的,服务器只能认,这叫注销难。

那怎么办呢?搞一个黑名单呗,把那些虽然没到期但已经被注销的令牌扔进黑名单里,每次校验的时候,除了看令牌本身,还得查一下它是不是在黑名单里,但这个黑名单放哪儿?要是还放数据库里,每次验证都去查数据库,数据库哪受得了这个压力,尤其是用户量一大,全挤在查黑名单这一步,肯定崩。

用Redis集群搭建那个能扛住压力又安全的JWT验证服务,感觉挺靠谱的

Redis就派上用场了,Redis这东西,速度飞快,全内存操作,读写的速度比数据库高好几个量级,正好适合干这种高频次、简单查询的活儿,把黑名单放在Redis里,查起来就快多了,服务器压力瞬间小很多。

但单机的Redis也可能出问题,万一这台机器宕机了,整个验证服务就瘫痪了,所有用户都登录不上,这肯定不行,所以得用Redis集群,集群的意思就是弄好多台Redis服务器,让它们一起干活儿,数据会在这些机器上分片存放,互相之间还有备份,这样有几个好处:第一是容量大了,能存更多的黑名单令牌;第二是性能好了,请求可以分散到不同的机器上处理;第三就是安全了,哪怕其中一两台机器挂了,其他的还能继续提供服务,不影响用户登录验证,这就叫高可用。

用Redis集群搭建那个能扛住压力又安全的JWT验证服务,感觉挺靠谱的

具体做起来大概是这么个流程:用户登录成功,服务器生成一个JWT令牌给他,同时呢,可以把这个JWT令牌的唯一标识(比如jti)或者干脆把整个令牌作为key,存到Redis集群里,并设置一个过期时间,这个时间可以和JWT本身的过期时间一致,或者稍微短一点都行,这时候,这个令牌在Redis里的存在,并不代表它是黑名单,而是代表它是“已签发”的有效令牌,当用户主动退出登录时,服务器就直接把Redis里对应的这个key删掉,下次这个用户再拿着同一个令牌来访问,服务器校验JWT本身通过后,再去Redis集群里查,发现这个key已经没了(或者查不到),那就拒绝访问,如果想更直接点,也可以在用户注销时,不是删除key,而是设置一个标记,比如把值设为"logout",然后查询的时候看值是不是这个标记。

还有一种思路是,登录时根本不往Redis里写,就保持JWT无状态的原汁原味,只有当用户注销时,才把这个令牌标识塞进Redis黑名单,并设置一个过期时间(等于这个令牌剩余的有效期),验证时,只要在Redis黑名单里没找到这个令牌,就放行,这样对Redis的写入压力更小,只有注销操作才写。

用Redis集群来扛,无论哪种方式,面对海量用户和频繁的验证请求,都能比较轻松地应对,而且Redis本身也支持密码认证、网络隔离这些安全措施,能保证黑名单数据不被随便访问,这样一套组合拳下来,既保留了JWT无状态、扩展性好的优点,又通过Redis集群解决了即时注销和承载高并发验证的问题,确实是个挺靠谱的方案。