前言

JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样。

  1. {
  2. "姓名": "张三",
  3. "角色": "管理员",
  4. "到期时间": "2018年7月1日0点0分"
  5. }

以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。
服务器就不保存任何 用户凭证数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。
然而,如果使用JWT实现,用户主动注销、强制登出(禁止登陆)、忘记密码、修改密码,JWT续签等方面的需求,就会让人头疼。

解决方案

根治

黑名单校验

凡是退出登录的token都放入黑名单中,定期清理。
每次用户请求服务器都校验token是否在黑名单

版本号校验

访问时从token中取出版本号和用户id 和 redis中存储 用户id和版本号 做对比,不一致则不给访问。
用户登出的时候在redis中把用户版本号加一。

过期时间校验

登录时token附带创建时间。访问时校验redis存储的过期时间,如果创建时间大于过期时间则不给访问。

Token副本校验

在redis中存储token副本,用户请求时候校验,如果redis中不存在该副本则不给通过。

无为而治

只让前端清理token,后端不理会。(大多数)

大体方案

分而治之

  1. 对于需要只有一个人一个终端登录的服务采用【版本号校验】解决方案
    1. 相当于乐观锁,但是用redis来实现,速度快
    2. 还方便踢人下线
  2. 对于需要注销token的服务,采用【Token副本校验 or 过期时间校验】解决方案
    1. 比查阅黑名单列表还要快得多
    2. 速度相当快
  3. 对于不需要注销token(大部分服务),则采用【无为而治】解决方案
    1. 完美的JWT登录的使用方式

      参考和引用

      JSON Web Token 入门教程
      关于JWT用户主动注销、强制登出、忘记密码、修改密码的一些思考
      在退出登录 / 修改密码时怎样实现JWT Token失效?