JWT官网 https://jwt.io
简单粗暴地说, jwt是一个由服务端创建但不存储, 带有效期和签名的结构化字符串.
关于jwt的应用, 基于目前的学习和使用情况, 做个总结.
1, 谈jwt, 为什么有人提redis和cookie
提到redis很正常, 因为如果你之前把token信息是放在服务端的redis里, 那么使用jwt一定可以节省你的服务器资源.
提到cookie让人误解, 以为jwt是来代替cookie的. 其实他们没有半毛钱关系, cookie会被浏览器管理, 而jwt只是一个独立的字符串而已, 这个串你也可以放在cookie里“存储”. 在没有jwt之前, 那些觉得cookie不好的人,会考虑localStorage等 ; 在有了jwt之后, 你还是得考虑在客户端给jwt串找个存储的地方.
2, 甚嚣尘上的jwt会话管理
jwt做会化管理, 去中心化, 不仅节省了服务端的资源, 而且代码量也节省了不少, 感觉清爽很多.
但jwt做会话管理确实存在一些弊端, 让人浅尝辄止, 下面针对主要问题做个解析.
2.1, 会话安全问题
有人说“对jwt串进行base64解码就能看见里面的敏感信息...”
这么说有点唬人, 因为敏感信息问题在cookie或者别的技术下也会存在, 不管你使用什么技术, 客户端就不应该存储敏感信息.
也还有人说“jwt串可以拷贝到任何地方使用...”
其实像cookie也一样可以拷贝, 如果拿这些来反驳jwt不安全, 是站不住脚的, 这些问题在jwt诞生之前就一直存在, 也不是jwt应该考虑的.
恰恰是因为jwt自带的签名机制, 在传输上做到了防篡改, 这一点挺安全的.
Q: 那么会话安全问题出在哪?
我觉得是, 服务端可以控制jwt的“生”,但控制不了jwt的“死”, 就是下面要说的会话销毁问题.
2.2, 会话销毁问题
服务端生成了带会话有效期的jwt串, 但因为服务端没有缓存它, 因而无法主动去销毁它.
在网上查阅资料时, 看到有人为了专门解决这个问题, 就在服务端利用redis来缓存jwt. 这个就有点太荒谬了, 因为你使用jwt的初衷, 就是为了“不用在服务端缓存会话信息”, 这也是jwt的优势. 否则直接使用reids进行会话管理就行了, jwt+redis 折腾了半天, 不仅资源没节省, 代码量和逻辑量倒是翻了倍.
Q: 那么怎么解决会话销毁问题呢?
我的观点是, 解决问题最好的方式, 就是“恰恰”不需要去解决它.
大多数业务系统没有主动销毁会话的需求, 或者不销毁也不会产生什么后果, 那这个销毁问题就不存在, 否则你就应该弃用jwt.
2.3, 会话延长问题
会话延长一般是这样的:
假如会话时长是20分钟,用户在9:00登陆成功.当用户在9:01操作向后台发送了请求,那么有效期会被延长到9:21,依此类推.
如果像这样延长会话, 那么服务端只能不停地生成新的jwt串, 这样虽不会出现大的性能问题, 但是服务端给客户端颁发了大量无法销毁的jwt, 这个逻辑很怪异.
Q: 那么怎么优化会话延长问题呢?
我觉得是, 当会话有效期还剩“不到一半时间”时, 再考虑延长. 这样会话有效期内, 延长的机会就只有一次, 只会新生成一个jwt. 如果对外需要保留原来的会话时长, 那么改为jwt方式之后, 将原先的会话时长翻倍即可.
当然还是那句梗, 解决问题最好的方式, 就是“恰恰”不需要解决. 如果可以忽略体验, 就是用户一直操作, 在达到会话边界时, 你突然间提示它会话超时, 用户可以接受, 那么服务端就不用考虑会话延长了, 生成完jwt之后直到它到过期.
3, jwt主要应用场景
jwt自带有效期和签名防篡改的特性, 在服务接口的token认证场景中, 可以替代传统服务端缓存token的方式, 更加简洁和高效.