jwt实现踢人下线的方法推荐

我曾经使用过一种方法:

那就是在生成jwt令牌时,加入一个固定的参数当做token生成的salt,如果要将一个用户踢出下线,只需要重新生成一下salt的值,然后在拦截器里每次校验这个salt生成的令牌是否与客户端传递的令牌一致!即可判断出这个token是否已被拉黑。

但是这种方法依然在服务器端存储了一定的数据,违反了其无状态性,有没有什么更好的方法实现?

阅读 13.6k
6 个回答

jwt 本身就是无状态的,关于踢人,要保持无状态,确实没有特别好的办法。不过有其他办法辅助,比如将token 的过期时间设置得特别短,然后用refresh_token来补充,这本身也是oauth2的原意。说jwt设计鸡肋也不太合适,jwt只是更加接近理想话的水平。不能忽略无状态带来的巨大优势,绝对的并发安全和流畅,不占用资源,不阻塞。就像java中的不可变对象一样,用起来总是不那么如意,但在合适的场景下却能发挥巨大作用。

web服务本身就是无状态的,何来违反了其无状态性。
什么是有状态?第一次请求需要根据token查db/redis,第二次不需要。这是有状态。
而web服务是每一次都需要根据token查db/redis。所以是无状态的。

中心化的方式在服务侧维护一些数据是必要的,不能认为破坏了“服务端无状态”。相比之下,你更需要注意的是,不要在某台服务器上维护状态,这才是大忌。

没有更好的方案,只能“有状态”

不太同意楼上的观点,HTTP 无状态(stateless)指的是协议本身无状态,一次请求到响应就结束了,再次请求又是新的。

但是 HTTP 协议上的 session 机制,其实是有状态(stateful)的,在无状态的 HTTP 协议上增加了 会话的概念,HTTP Server 需要为每一个 Session(id) 来保存数据,所以是有状态的。

letting the servers maintain a stateful session over the mostly stateless HTTP protocol.

https://datatracker.ietf.org/...

JWT 就属于无状态,因为 Server 并没有为每个“会话”保存状态。而将 JWT token 保存至 Server 的这种行为就打破了无状态,这也是 JWT 这种 Stateless 设计的一个弊端,Server 无法控制客户端的行为。

JWT 再加上 token 存 Server 端,就有点脱裤子放屁的意思了,不如直接 token 存 redis,不用 JWT ……

个人认为 JWT 这种设计比较鸡肋,不适用大多数的业务场景,就连用户禁用这个小功能都做不了,更别提“踢人下线”了

后台向前端传递一个退出标识保存到客户端,前端检测到该标识则退出登录。如cookie

其实你没必要保存salt啥的作为踢人的判断,踢人可以看作是用户对某些接口的一种权限状态,你踢人的时候,去除他对一些接口的访问权限,当权限被禁止,他是在线还是离线,对你来说无关紧要。前端做一个判断,权限被禁就直接下线。
更简单一点的做法,你给他用户信息表增加字段做个标识,如果该用户被标记为禁封,就不允许登录以及访问其它接口。我之前在实际项目中,对一些特定设备的控制就是这么干的,这与token啥的登录状态无关,挺好用。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏