JWT 身份认证优缺点分析以及常见问题解决方案( 二 )

  • 修改密钥 (Secret) : 我们为每个用户都创建一个专属密钥,如果我们想让某个 token 失效,我们直接修改对应用户的密钥即可 。但是,这样相比于前两种引入内存数据库带来了危害更大,比如:1??如果服务是分布式的,则每次发出新的 token 时都必须在多台机器同步密钥 。为此,你需要将必须将机密存储在数据库或其他外部服务中,这样和 Session 认证就没太大区别了 。2??如果用户同时在两个浏览器打开系统,或者在手机端也打开了系统,如果它从一个地方将账号退出,那么其他地方都要重新进行登录,这是不可取的 。
  • 保持令牌的有效期限短并经常轮换 :很简单的一种方式 。但是,会导致用户登录状态不会被持久记录,而且需要用户经常登录 。
  • 对于修改密码后 token 还有效问题的解决还是比较容易的,说一种我觉得比较好的方式:使用用户的密码的哈希值对 token 进行签名 。因此,如果密码更改,则任何先前的令牌将自动无法验证 。
    2.token 的续签问题
    token 有效期一般都建议设置的不太长,那么 token 过期后如何认证,如何实现动态刷新 token,避免用户经常需要重新登录?
    我们先来看看在 Session 认证中一般的做法:假如 session 的有效期30分钟,如果 30 分钟内用户有访问,就把 session 有效期被延长30分钟 。
    1. 类似于 Session 认证中的做法:这种方案满足于大部分场景 。假设服务端给的 token 有效期设置为30分钟,服务端每次进行校验时,如果发现 token 的有效期马上快过期了,服务端就重新生成 token 给客户端 。客户端每次请求都检查新旧token,如果不一致,则更新本地的token 。这种做法的问题是仅仅在快过期的时候请求才会更新 token ,对客户端不是很友好 。
    2. 每次请求都返回新 token :这种方案的的思路很简单,但是,很明显,开销会比较大 。
    3. token 有效期设置到半夜 :这种方案是一种折衷的方案,保证了大部分用户白天可以正常登录,适用于对安全性要求不高的系统 。
    4. 用户登录返回两个 token :第一个是 acessToken,它的过期时间 token 本身的过期时间比如半个小时,另外一个是 refreshToken 它的过期时间更长一点比如为1天 。客户端登录后,将 accessToken和refreshToken 保存在本地,每次访问将 accessToken 传给服务端 。服务端校验 accessToken 的有效性,如果过期的话,就将 refreshToken 传给服务端 。如果有效,服务端就生成新的 accessToken 给客户端 。否则,客户端就重新登录即可 。该方案的不足是:1??需要客户端来配合;2??用户注销的时候需要同时保证两个 token 都无效;3??重新请求获取 token 的过程中会有短暂 token 不可用的情况(可以通过在客户端设置定时器,当accessToken 快过期的时候,提前去通过 refreshToken 获取新的accessToken) 。
    总结
    JWT 最适合的场景是不需要服务端保存用户状态的场景,比如如果考虑到 token 注销和 token 续签的场景话,没有特别好的解决方案,大部分解决方案都给 token 加上了状态,这就有点类似 Session 认证了 。
    欢迎做Java的朋友们私信我【资料】免费获取免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,MySQL,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)
    其中覆盖了互联网的方方面面,期间碰到各种产品各种场景下的各种问题,很值得大家借鉴和学习,扩展自己的技术广度和知识面 。

    【JWT 身份认证优缺点分析以及常见问题解决方案】


    推荐阅读