139
社区成员
技术:实现jwt黑名单解决jwt无状态问题。
使用技术:主要使用redis实现jwt黑名单同时嵌入原有的SpringBoot+SpringSecurity+Redis的框架中
原因:由于Jwt的无状态性服务器只知道这个token是否合法以及是否过期,不知道此时token是否有效,例如如果用户账号密码被盗,由于Jwt的无状态性,服务器会在一段时间内都认为jwt有效,此时用户修改密码,并不能使之前以及颁发过的token失效,就存在安全漏洞。难点:该使用什么作为黑名单的基准以及如何嵌入原有框架。
前言:由于 JWT 是无状态的,只能等到它的有效期过了才会失效,服务端无法主动让一个 token 失效,为了解决这个问题,需要jwt失效策略。这里使用黑名单策略并且用redis实现来解决 JWT 的主动失效问题。通过一个查询黑名单(记录失效的token或者已经失效的条件)判断token是否在黑名单中如果在就判定为失效。
实现:基于Jwt可以携带信息的特性,让Jwt携带颁发时间并且通过Redis快速查询的特性记录每个用户Jwt的最新颁发时间也可以称失效时间,凡是在失效时间之前创建的Jwt都判定失效。通过一张图来说明。
实现步骤:
1.用户登入或注销等一系列需要使Jwt主动失效的方法中更新黑名单(redis)中最新颁发时间。
2.如果用户为登入则在更新Redis最新发布时间之后。颁发token时候记录颁发时间并让jwt携带颁发时间。(这里有个坑一定要先更新redis的黑名单失效时间再颁发token)
3.在jwt过滤器中(springsecurity 结合Jwt最主要就是这个Jwt过滤器并且注入到SpringSecurity过滤链中)调用的Jwt验证的相关代码
判断jwt颁发时间是否在黑名单之后,在之前直接判定失效。
代码
1.更新黑名单
2.将颁发时间携带入Jwt
3.修改验证逻辑
前述:过程还是比较顺利,只要理清逻辑顺序就能够准确无误的完成这个功能。下面思考可能会出现的问题。
1.每次颁发的token都在黑名单中认证失效
可能是没有先更新黑名单而是先颁发token再更新黑名单,就有可能导致黑名单中的时间每次都比刚刚颁发的token的时间晚几秒。
2.已过期的Token或者明明应该失效的Token确能够使用
使用Jwt有许多好处可以预防Csrf问题也同时在分布式系统中有很大用武之地同时也有相应的坏处,由于Jwt的无状态性服务器只知道这个token是否合法以及是否过期,存在一定程度局限性,因为服务器不知道此时token是否有效,例如如果用户账号密码被盗,由于Jwt的无状态性,服务器会在一段时间内都认为jwt有效,此时用户修改密码,并不能使之前以及颁发过的token失效,就存在安全漏洞。总之从意识到这层面的问题到解决问题都让我收获颇丰。
SpringBoot + SpringSecurity + Mybatis-Plus + JWT + Redis 实现分布式系统认证和授权(刷新Token和Token黑名单)
作者:C3Stones