在构建 Web 应用程序时,用户认证和会话管理是关键部分。我发现,无论什么场景,很多开发者都倾向于使用 JWT(JSON Web Token)来替代传统的 Session 机制实现用户认证和会话管理。有些开发者甚至认为 Session 是旧时代的产物,应该被淘汰,使用 JWT 才是标准和未来,还有一些开发者甚至都没有真正去了解过 JWT。
很多文章都在讨论 JWT 和 Session 的不同,但我认为这种讨论是相对比较片面的。
大多数人对 Session 机制的偏见
许多人对 Session 机制缺乏深入了解,仅凭道听途说,因此形成了一些偏见:
认为 Session 消耗服务器资源,仅仅是因为 Session 数据都需要存储在内存中。
其实通过优化存储策略和清理机制,Session 对服务器资源的占用可以被有效管理,不会导致严重的资源消耗和性能问题。
认为 Session 不支持分布式,也是因为数据存储在应用服务内存中,无法实现或难以实现跨服务的共享。
在分布式场景下,可以通过分布式缓存服务(例如:Redis)来解决。在 Spring 中,也有针对性的实现(例如:Spring Session),对开发者而言是透明的,无需关心具体实现。
认为 Session 不支持跨域,因为 Session 是基于 Cookie 的,而 Cookie 有跨域限制。
实际上,Session 机制并不只依赖于 Cookie,只是大多数情况下会使用 Cookie 来传递 Session ID 而已。除了可以配置 Cookie 支持跨域,但也可以通过其他方式传递 Session ID,例如:URL 参数、Header 等。
JWT 的主要问题
许多人有了前面的对 Session 机制的一些偏见,却又忽略了 JWT 的问题。Session 机制确实无法做到像 JWT 的自包含和无状态,但是,在会话管理这个场景,本身就是需要有状态的,JWT 的无状态优势并不适用于此,反而会增加一些不可避免的问题:
- 无法主动注销:一旦签发了 JWT,就无法主动让其失效,只能等待其过期。
- 无法延长会话:一旦签发了 JWT,就无法延长会话时间,只能重新签发,即无法更新。
如果一定要实现主动注销,则需要在服务端维护一个黑名单,将要被注销的 JWT 加入黑名单,然后在验证 JWT 时,先检查黑名单。这样一来,不就是相当于在 JWT 上又加了一层 Session 机制吗?并且,这个 Session 机制还不如传统的 Session 机制。
这两个需求,在实际应用中是必不可少的,如果使用 JWT,需要自己实现这些逻辑,而使用传统的 Session 机制,这些都是内置的功能。
适合 JWT 的场景
JWT 非常适合一些需要短期认证的场景,例如:
- 临时访问权限:在某些情况下,需要为用户授予临时的访问权限,例如在特定时间段内访问某些资源,JWT 可以很好地满足这种需求。
- 验证链接:用户注册后,需要验证邮箱,或者用户忘记密码,需要重置密码,可以使用 JWT 来生成验证链接。
总结
JWT 和 Session 有其各自所解决的问题和最佳的适用场景,在实际应用中应根据具体需求来抉择,甚至可以结合两种机制来达到最佳效果。并不存在谁替代谁,深入了解各自的特点和适用场景才是关键。