你在用 JWT 代替 Session?

現在婿屹,JSON Web Tokens (JWT) 是非常流行的灭美。尤其是 Web 開發(fā)領域。

  • 流行
  • 安全
  • 穩(wěn)定
  • 易用
  • 支持 JSON

所有這些因素昂利,令 JWT 名聲大振届腐。

但是,今天我要來說說使用 JWT 的缺點蜂奸。也就是為什么說將 JWT 用于會話控制是多么的糟糕犁苏。

為什么使用 JWT?

如果你不了解 JWT扩所,不要緊張围详,它并不可怕。

JWT 只是用于網絡間傳遞聲明而執(zhí)行一種基于 JSON 的標準祖屏。

例如助赞,我是個盲人,而且聽力也不好袁勺。你上周幫我買了午餐雹食,現在我需要你的收款賬號,把錢還給你期丰。如果我詢問你的賬號群叶,但是其他人高呼他們的賬號,由于我把別人的賬號誤認為是你的钝荡,我可能會不小心把錢打給別人街立。

JWT 旨在防止這種情況發(fā)生。JWT 提供了一種簡單的方法化撕,在彼此傳遞數據時几晤,驗證是由誰先創(chuàng)建了數據。

所以植阴,像上述的例子蟹瘾,即使我收到了超過 100 萬個 JWT 返回的賬號信息圾浅,我也很容易可以辨別出來哪個真實來自于你。

JWT 如何運行憾朴?

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

image

JWT 的核心是密鑰,就是 JSON 數據众雷。這是你關心的灸拍,并希望安全傳遞出去的數據。JWT 如何做到這一點砾省,并使你信任它鸡岗,就是加密簽名。

比如說编兄,我寫了一封信轩性,當我署名這封信時,意味著只要讀過這封信的人狠鸳,都知道是我寫了這封信揣苏。而且我的簽名是獨一無二的,所以不會被懷疑真實性件舵。加密簽名的方式大致相同卸察,JWT 有兩種加密方式:對稱加密和非對稱加密,兩種方式有同等的效用铅祸。

JWT 內容加密

其實坑质,JWT 的內容(內部的 JSON 數據)通常是不加密的。這意味著临梗,即使沒有密鑰洪乍,也可以查看 JWT 內的數據。JWT 默認并不會加密你的數據夜焦,它只是幫助你驗證是你信任的一方創(chuàng)建了它。

如果你確實需要加密 JWT 內容岂贩,可以使用 JWE 進行加密茫经,但這種做法并不常見。請確保使用了正確的方法萎津。

如今人們是如何使用 JWT 的卸伞?

JWT 最常見的用途是身份驗證。有大量的 Web 安全庫使用 JWT 創(chuàng)建會話控制锉屈,API 令牌等荤傲。

這種做法通常是,當需要對網站/ API 進行身份驗證時颈渊,服務器生成一個包含用戶 ID 的 JWT遂黍,以及其它一些關鍵性的信息终佛,然后再將其發(fā)送給瀏覽器/客戶端等,存儲為會話令牌雾家。

image

例如铃彰,當用戶訪問網站上的另一個頁面時,瀏覽器會自動將該 JWT 發(fā)送到服務器芯咧,服務器驗證 JWT 確認和最初創(chuàng)建的令牌相同牙捉,然后允許用戶執(zhí)行后續(xù)的操作。

從理論上看敬飒,還不錯邪铲,因為:

  • 當服務器收到 JWT 時,可以驗證其是否是合法的无拗,是否是信任用戶的令牌
  • 可以在服務器本地驗證带到,而不需要任何其它的網絡請求,與數據庫的通信等蓝纲。這可能令管理會話更高效阴孟,因為無需從數據庫(緩存)加載用戶信息,只需要在本地運行一小部分代碼税迷。這可能是人們喜歡用 JWT 的最大原因永丝。

似乎很棒,既可以提高 Web 應用的性能箭养,又可以減少緩存服務器和數據庫服務器的負載慕嚷,提供更好的體驗。另外你還可以在 JWT 中存儲用戶權限信息毕泌、用戶個人信息等等更多的額外信息進一步減少數據庫壓力喝检。

為什么 JWT 不是最好的會話令牌?

我們已經了解了 JWT 如何用于身份驗證撼泛,讓我們進入本篇的中心話題:為什么 JWT 不是最好的會話令牌挠说,為什么普通的舊會話方式在幾乎各方面都優(yōu)于 JWT。

背景

我們先了解一些背景知識愿题。開發(fā)人員構建的大多數網站都相對比較簡單:

  • 用戶注冊
  • 用戶登錄
  • 用戶點擊執(zhí)行操作
  • 網站使用用戶信息進行創(chuàng)建损俭、刪除、更新潘酗、查閱信息

對于這類網站杆兵,要知道用戶進行交互的每個頁面都會包含某些動態(tài)數據。比如:你正在訪問一個需要用戶登錄才能進一步操作的網站仔夺,你經常會在數據庫中對用戶進行這些操作:

  • 記錄用戶正在執(zhí)行的操作
  • 將用戶的某些信息添加到數據庫中
  • 檢查用戶的權限看其是否可以執(zhí)行某項操作
  • 等等

數據

我們來看兩種方案:

  • 在 Cookie 中存儲用戶 ID(abc123)
  • 在 JWT 中存儲用戶 ID(abc123)

如果我們將 ID 存儲在 Cookie 中琐脏,需要 6 個字節(jié)。如果將 ID 存儲在 JWT 中(設置基本的請求頭字段,以及一些其它信息)日裙,需要幾百字節(jié)甚至更多吹艇。對于簡單的會話控制,每個頁面的請求就增大了幾十倍阅签。

image

假如你的網站每月有 10 萬次的瀏覽器掐暮,就意味著要多開銷幾十兆的流量。聽起來并不多政钟,但日積月累也是不小一筆開銷路克。實際上,許多人會在 JWT 中存儲的信息會更多养交。

無論如何你需要操作數據庫

如上所述精算,大多數需要用戶登錄的網站主要是 CRUD 操作(增查改刪)生成動態(tài)內容。

image

在網站上使用 JWT碎连,對于用戶加載的幾乎所有頁面灰羽,都需要從緩存/數據庫中加載用戶信息,可能出現下列情況:

  • 需要用戶關鍵性信息查詢(例如:判斷用戶賬號是否有足夠的資金完成交易鱼辙?)
  • 需要將一些信息保存進數據庫(例如:用戶相關的唯一信息廉嚼,需要根據該信息對用戶進行檢索)
  • 必須從緩存/數據庫中查詢完整的信息,方便網站生成完整的動態(tài)頁面內容倒戏。

想想你的網站是否會遇到上述情形怠噪。這意味著大多數網站不適用 JWT 的無狀態(tài)特性。為了解決這個問題杜跷,就需要 JWT 變得更大傍念,而且需要使用 CPU 來計算簽名,就會導致比傳統(tǒng)會話慢許多葛闷。

其實憋槐,幾乎每個 Web 框架支持在每次請求傳入用戶信息,這包括 Django淑趾,Rails阳仔,Express.js 等(如果有用到身份驗證功能)。另外扣泊,如果你使用 Memcached/Redis 等緩存服務器對用戶信息進行緩存驳概,檢索會變得非常快旷赖。

多余的簽名

JWT 的賣點之一就是加密簽名,由于這個特性更卒,接收方得以驗證 JWT 是否有效且被信任等孵。

但是,其實在過去 20 年中幾乎每一個框架對于普通會話 Cookie 都可以獲得很好的加密簽名處理蹂空。這意味著你可以獲得與 JWT 完全一致的效果俯萌,況且大多數 Web 身份認證應用中果录,JWT 都會被存儲到 Cookie 中,這就是說你有了兩個層面的簽名咐熙。

聽著似乎很贊弱恒,但是沒有任何優(yōu)勢,為此棋恼,你需要花費兩倍的 CPU 開銷來驗證簽名返弹。對于有著嚴格性能要求的 Web 應用,這并不理想爪飘,尤其對于單線程環(huán)境义起。

更好的解決方案是什么?

如果你正在構建上述類型的網站师崎,那么最好選擇舊的默终,簡單且安全的服務器端會話。而不是將用戶 ID 存儲到 JWT 中犁罩,然后再將 JWT 存儲到 Cooike 中齐蔽。只需將用戶 ID 直接存儲到 Cookie 中即可。

如果你的網站很受歡迎床估,有著大的訪問量含滴,可以將會話緩存到 Memcached/Redis,同時也有利于擴展你的服務顷窒。

什么時候使用 JWT蛙吏?

JWT 雖然對于大多數網站都沒有用逼裆,但是有幾種情況它是很有用的捉偏。

如果你正在構建從服務器到服務器或客戶端到服務器(如:移動應用 APP 或單頁面應用)的 API 服務,那么使用 JWT 是非常明智的贝或。比如:

  • 你的客戶端需要通過 API 進行身份驗證谓着,并返回 JWT
  • 然后泼诱,客戶端使用返回的 JWT 經過身份驗證去請求其它的 API 服務
  • 這些其它 API 服務通過客戶端的 JWT 驗證客戶端是可信的,并且可以執(zhí)行某些操作無需再次驗證
image

對于這類 API 服務赊锚,JWT 非常適合治筒,因為客戶端需要頻繁進行請求,并且權限是可控的舷蒲,通常認證數據以無狀態(tài)方式持久存在耸袜,不需要過多依賴用戶信息。

如果你正在構建的應用類似單點登錄或 OpenID Connect 認證牲平,JWT 同樣十分適合堤框,就是實現一種通過第三方驗證用戶的方法。

總結

當你準備構建下一個網站時,只需要使用 Web 框架默認的身份認證功能即可蜈抓,不需要再集成 JWT 方式启绰。


關注公眾號「展白說」,獲取更多有價值的信息沟使。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末委可,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子腊嗡,更是在濱河造成了極大的恐慌着倾,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叽唱,死亡現場離奇詭異屈呕,居然都是意外死亡,警方通過查閱死者的電腦和手機棺亭,發(fā)現死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門虎眨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人镶摘,你說我怎么就攤上這事嗽桩。” “怎么了凄敢?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵碌冶,是天一觀的道長。 經常有香客問我涝缝,道長扑庞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任拒逮,我火速辦了婚禮罐氨,結果婚禮上,老公的妹妹穿的比我還像新娘滩援。我一直安慰自己栅隐,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布玩徊。 她就那樣靜靜地躺著租悄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恩袱。 梳的紋絲不亂的頭發(fā)上泣棋,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音畔塔,去河邊找鬼外傅。 笑死纪吮,一個胖子當著我的面吹牛,可吹牛的內容都是我干的萎胰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼棚辽,長吁一口氣:“原來是場噩夢啊……” “哼技竟!你這毒婦竟也來了?” 一聲冷哼從身側響起屈藐,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤榔组,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后联逻,有當地人在樹林里發(fā)現了一具尸體搓扯,經...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年包归,在試婚紗的時候發(fā)現自己被綠了锨推。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡公壤,死狀恐怖换可,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情厦幅,我是刑警寧澤沾鳄,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站确憨,受9級特大地震影響译荞,放射性物質發(fā)生泄漏。R本人自食惡果不足惜休弃,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一吞歼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧玫芦,春花似錦浆熔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至老虫,卻和暖如春叶骨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背祈匙。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工忽刽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留天揖,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓跪帝,卻偏偏與公主長得像今膊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子伞剑,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容