你在用 JWT 代替 Session?

如今,JSON Web Tokens (JWT) 是很是流行的。尤为是 Web 开发领域。web

  • 流行
  • 安全
  • 稳定
  • 易用
  • 支持 JSON

全部这些因素,令 JWT 名声大振。数据库

可是,今天我要来讲说使用 JWT 的缺点。也就是为何说将 JWT 用于会话控制是多么的糟糕。浏览器

为何使用 JWT?

若是你不了解 JWT,没关系张,它并不可怕。缓存

JWT 只是用于网络间传递声明而执行一种基于 JSON 的标准。安全

例如,我是个盲人,并且听力也很差。你上周帮我买了午饭,如今我须要你的收款帐号,把钱还给你。若是我询问你的帐号,可是其余人高呼他们的帐号,因为我把别人的帐号误认为是你的,我可能会不当心把钱打给别人。服务器

JWT 旨在防止这种状况发生。JWT 提供了一种简单的方法,在彼此传递数据时,验证是由谁先建立了数据。markdown

因此,像上述的例子,即便我收到了超过 100 万个 JWT 返回的帐号信息,我也很容易能够辨别出来哪一个真实来自于你。网络

JWT 如何运行?

JWT 是 JSON 格式的被加密了的字符串。框架

JWT 的核心是密钥,就是 JSON 数据。这是你关心的,并但愿安全传递出去的数据。JWT 如何作到这一点,并使你信任它,就是加密签名。svg

好比说,我写了一封信,当我署名这封信时,意味着只要读过这封信的人,都知道是我写了这封信。并且个人签名是独一无二的,因此不会被怀疑真实性。加密签名的方式大体相同,JWT 有两种加密方式:对称加密和非对称加密,两种方式有同等的效用。

JWT 内容加密

其实,JWT 的内容(内部的 JSON 数据)一般是不加密的。这意味着,即便没有密钥,也能够查看 JWT 内的数据。JWT 默认并不会加密你的数据,它只是帮助你验证是你信任的一方建立了它。

若是你确实须要加密 JWT 内容,可使用 JWE 进行加密,但这种作法并不常见。请确保使用了正确的方法。

现在人们是如何使用 JWT 的?

JWT 最多见的用途是身份验证。有大量的 Web 安全库使用 JWT 建立会话控制,API 令牌等。

这种作法一般是,当须要对网站/ API 进行身份验证时,服务器生成一个包含用户 ID 的 JWT,以及其它一些关键性的信息,而后再将其发送给浏览器/客户端等,存储为会话令牌。

例如,当用户访问网站上的另外一个页面时,浏览器会自动将该 JWT 发送到服务器,服务器验证 JWT 确认和最初建立的令牌相同,而后容许用户执行后续的操做。

从理论上看,还不错,由于:

  • 当服务器收到 JWT 时,能够验证其是不是合法的,是不是信任用户的令牌
  • 能够在服务器本地验证,而不须要任何其它的网络请求,与数据库的通讯等。这可能令管理会话更高效,由于无需从数据库(缓存)加载用户信息,只须要在本地运行一小部分代码。这多是人们喜欢用 JWT 的最大缘由。

彷佛很棒,既能够提升 Web 应用的性能,又能够减小缓存服务器和数据库服务器的负载,提供更好的体验。另外你还能够在 JWT 中存储用户权限信息、用户我的信息等等更多的额外信息进一步减小数据库压力。

为何 JWT 不是最好的会话令牌?

咱们已经了解了 JWT 如何用于身份验证,让咱们进入本篇的中心话题:为何 JWT 不是最好的会话令牌,为何普通的旧会话方式在几乎各方面都优于 JWT。

背景

咱们先了解一些背景知识。开发人员构建的大多数网站都相对比较简单:

  • 用户注册
  • 用户登陆
  • 用户点击执行操做
  • 网站使用用户信息进行建立、删除、更新、查阅信息

对于这类网站,要知道用户进行交互的每一个页面都会包含某些动态数据。好比:你正在访问一个须要用户登陆才能进一步操做的网站,你常常会在数据库中对用户进行这些操做:

  • 记录用户正在执行的操做
  • 将用户的某些信息添加到数据库中
  • 检查用户的权限看其是否能够执行某项操做
  • 等等

数据

咱们来看两种方案:

  • 在 Cookie 中存储用户 ID(abc123)
  • 在 JWT 中存储用户 ID(abc123)

若是咱们将 ID 存储在 Cookie 中,须要 6 个字节。若是将 ID 存储在 JWT 中(设置基本的请求头字段,以及一些其它信息),须要几百字节甚至更多。对于简单的会话控制,每一个页面的请求就增大了几十倍。

假如你的网站每个月有 10 万次的浏览器,就意味着要多开销几十兆的流量。听起来并很少,但日积月累也是不小一笔开销。实际上,许多人会在 JWT 中存储的信息会更多。

不管如何你须要操做数据库

如上所述,大多数须要用户登陆的网站主要是 CRUD 操做(增查改删)生成动态内容。

在网站上使用 JWT,对于用户加载的几乎全部页面,都须要从缓存/数据库中加载用户信息,可能出现下列状况:

  • 须要用户关键性信息查询(例如:判断用户帐号是否有足够的资金完成交易?)
  • 须要将一些信息保存进数据库(例如:用户相关的惟一信息,须要根据该信息对用户进行检索)
  • 必须从缓存/数据库中查询完整的信息,方便网站生成完整的动态页面内容。

想一想你的网站是否会遇到上述情形。这意味着大多数网站不适用 JWT 的无状态特性。为了解决这个问题,就须要 JWT 变得更大,并且须要使用 CPU 来计算签名,就会致使比传统会话慢许多。

其实,几乎每一个 Web 框架支持在每次请求传入用户信息,这包括 Django,Rails,Express.js 等(若是有用到身份验证功能)。另外,若是你使用 Memcached/Redis 等缓存服务器对用户信息进行缓存,检索会变得很是快。

多余的签名

JWT 的卖点之一就是加密签名,因为这个特性,接收方得以验证 JWT 是否有效且被信任。

可是,其实在过去 20 年中几乎每个框架对于普通会话 Cookie 均可以得到很好的加密签名处理。这意味着你能够得到与 JWT 彻底一致的效果,何况大多数 Web 身份认证应用中,JWT 都会被存储到 Cookie 中,这就是说你有了两个层面的签名。

听着彷佛很赞,可是没有任何优点,为此,你须要花费两倍的 CPU 开销来验证签名。对于有着严格性能要求的 Web 应用,这并不理想,尤为对于单线程环境。

更好的解决方案是什么?

若是你正在构建上述类型的网站,那么最好选择旧的,简单且安全的服务器端会话。而不是将用户 ID 存储到 JWT 中,而后再将 JWT 存储到 Cooike 中。只需将用户 ID 直接存储到 Cookie 中便可。

若是你的网站很受欢迎,有着大的访问量,能够将会话缓存到 Memcached/Redis,同时也有利于扩展你的服务。

何时使用 JWT?

JWT 虽然对于大多数网站都没有用,可是有几种状况它是颇有用的。

若是你正在构建从服务器到服务器或客户端到服务器(如:移动应用 APP 或单页面应用)的 API 服务,那么使用 JWT 是很是明智的。好比:

  • 你的客户端须要经过 API 进行身份验证,并返回 JWT
  • 而后,客户端使用返回的 JWT 通过身份验证去请求其它的 API 服务
  • 这些其它 API 服务经过客户端的 JWT 验证客户端是可信的,而且能够执行某些操做无需再次验证

对于这类 API 服务,JWT 很是适合,由于客户端须要频繁进行请求,而且权限是可控的,一般认证数据以无状态方式持久存在,不须要过多依赖用户信息。

若是你正在构建的应用相似单点登陆或 OpenID Connect 认证,JWT 一样十分适合,就是实现一种经过第三方验证用户的方法。

总结

当你准备构建下一个网站时,只须要使用 Web 框架默认的身份认证功能便可,不须要再集成 JWT 方式。


原文地址:https://blog.csdn.net/weixin_41153791/article/details/82291144

相关文章
相关标签/搜索