# JWT 还是 Session

本项目最初使用 jwt 进行前后端验证,但一番实践后,最后还是改为 session 的机制,原因如下:

# 签发 token 失效问题

假设一个场景:用户在 A、B 两台电脑上都登录了系统,后端相应的也签发了两个 token,此时用户在 A 电脑上修改了密码,如何使 B 电脑的 token 失效?

方案:我在 user 表中添加了一个 jwtSecert 字段,用于存放每个用户自己的 jwt 私钥,而不是所有用户使用同一个私钥。一方面这样更安全,一个用户被暴力破解不会影响其他用户,另一个主要原因是 jwt 没有撤销签发 token 的机制,一旦签发 token,那在过期时间之前 token 一直有效,虽然前端退出登录自行删除了 token,但是这是一种假注销,我们需要一种真注销的方式,那就是改变这个用户的私钥。

# 频繁查库

上面的问题解释了每个用户都要有自己的密钥,于是每次验证 http 请求中的 token 时都要先从明文的 jwt 部分获取到当前用户的 username,然后用 username 去查库获取到这个用户的密钥,最后用密钥验证当前 token 是否有效。

# token 刷新问题

假设一个场景:用户 30 分钟不操作后自动退出登录。

用户登录后,后端签发了一个 30 分钟的 token,一分钟后,前端又发了一个请求给后端,此时后端应该刷新一下前端的 token,但是 jwt 并没有刷新的机制,只能重新签发一个 30 分钟的 token 给前端。

可以看到 jwt 本身没有刷新的机制,导致无法做这种实时刷新 token 的操作,只能退一步,例如用户还有 10 分钟要过期了,才重新签发一个 30 分钟的 token

相比于 session 机制,每次前端请求时,刷新一下内存中的 session 过期时间就行了

# 总结

jwt并不适合这种前后端认证的场景,更适合像验证邮件、OAuth授权等一次性临时认证的场景

参考文章:理解 JWT 的使用场景和优劣