你在用 JWT 代替 Session?

现在,JSON Web Tokens (JWT) 是非常流行的。尤其是 Web 开发领域。

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

所有这些因素,令 JWT 名声大振。

但是,今天我要来说说使用 JWT 的缺点。也就是为什么说将 JWT 用于会话控制是多么的糟糕。

为什么使用 JWT?

如果你不了解 JWT,不要紧张,它并不可怕。

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

例如,我是个盲人,而且听力也不好。你上周帮我买了午餐,现在我需要你的收款账号,把钱还给你。如果我询问你的账号,但是其他人高呼他们的账号,由于我把别人的账号误认为是你的,我可能会不小心把钱打给别人。

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

所以,像上述的例子,即使我收到了超过 100 万个 JWT 返回的账号信息,我也很容易可以辨别出来哪个真实来自于你。

JWT 如何运行?

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

image

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

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

JWT 内容加密

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

如果你确实需要加密 JWT 内容,可以使用 JWE 进行加密,但这种做法并不常见。请确保使用了正确的方法。

如今人们是如何使用 JWT 的?

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

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

image

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

从理论上看,还不错,因为:

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

似乎很棒,既可以提高 Web 应用的性能,又可以减少缓存服务器和数据库服务器的负载,提供更好的体验。另外你还可以在 JWT 中存储用户权限信息、用户个人信息等等更多的额外信息进一步减少数据库压力。

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

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

背景

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

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

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

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

数据

我们来看两种方案:

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

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

image

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

无论如何你需要操作数据库

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

image

在网站上使用 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 验证客户端是可信的,并且可以执行某些操作无需再次验证
image

对于这类 API 服务,JWT 非常适合,因为客户端需要频繁进行请求,并且权限是可控的,通常认证数据以无状态方式持久存在,不需要过多依赖用户信息。

如果你正在构建的应用类似单点登录或 OpenID Connect 认证,JWT 同样十分适合,就是实现一种通过第三方验证用户的方法。

总结

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


关注公众号「展白说」,获取更多有价值的信息。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容