首页
学习
活动
专区
圈层
工具
发布

redis中保存token(jwt)的意义是啥?

前几天晚上加班到快十二点,在工位那一边边撸串边跟我们组的小李扯皮,说到公司后端这套jwt token方案要不要加redis…大家都笑了,说这东西不是摆明了多此一举嘛,jwt自己不就带着有效期吗?不过其实还真不是每次都这么简单。

你先想啊,jwt这个东西本身确实能直接设置过期时间,比如7天免登录啥的,就JWT.create().withExpiresAt(...)随便一写,7天之内你token随便用都可以,服务端也不用保存啥状态,妥妥的无状态方案,看着特优雅。可现实呢,真出了问题的时候你就知道为啥有人偏要把jwt塞到redis里去了。

我举个最常见的,就是那种“主动登出”场景——你这不是说前端把token从sessionStorage里一删就行吗?理论上确实,前端把授权信息干掉了,页面一刷新,发啥请求都没token,就等于重新登录。问题是现在移动端、PC多端同步,你这token发出去,不光前端有,别人要是拿你token去别的端还不是一样能继续用?后端要想彻底把这token失效,没点黑科技真做不到。

就我们实际项目里,redis存jwt主要就是做“黑名单”或者“白名单”。举个栗子: 用户点了“退出登录”,后端收到请求就把这个token的jti(jwt id)加到redis一个集合里,后面所有接口校验jwt的时候,不仅要验签和过期时间,还得查一下这个jti在不在黑名单里,是不是已经被主动注销了。 像这样,服务端就有办法把还在有效期内的token也立马废掉,不然jwt一发出去,想收都收不回来,那就太刺激了。代码随便扔一段,反正大概就是这样:

// 用户主动登出

String jti = getJtiFromToken(token);

redisTemplate.opsForValue().set("jwt:blacklist:" + jti, "1", tokenTtl, TimeUnit.SECONDS);

// 校验jwt时

String jti = getJtiFromToken(token);

if (redisTemplate.hasKey("jwt:blacklist:" + jti)) {

  throw new UnauthorizedException("token已失效");

}

还有一种情况,之前遇到过。你想临时把某个用户踢下线,比如风控发现账号异常操作,后台点一下,把ta所有的token全作废。要不用redis做token管理,真不知道咋实现。 对了,有些公司用redis还搞“单点登录”,比如一账号只允许一个地方登录,后来登录的就把前面那个token踢掉,这玩意儿也只能靠服务端存token相关信息,比如userId <-> token的映射,redis最方便,内存方案一掉就全丢了。

其实你说“jwt存redis是不是多此一举”吧,也不是全无道理,真纯做简单项目,token有效期够短,用户体验也别太讲究,确实可以不存。但一碰上上面这些“必须强制失效”“后端干预”这种场景,redis就香了。

我上周就在厕所刷手机,看到群里有人问,说“jwt能不能和session机制一样支持服务端失效”,下面好几个大佬都说,jwt理论上是无状态,实际业务一复杂,没几个不用redis兜底的。大家都懂嘛,互联网那一套,实际情况比PPT里复杂多了。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OLiN8Ij_Iso2MqFbAuFCDQSQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。
领券