如今,JSON Web Tokens (JWT) 是很是流行的。尤爲是 Web 開發領域。web
全部這些因素,令 JWT 名聲大振。數據庫
可是,今天我要來講說使用 JWT 的缺點。也就是爲何說將 JWT 用於會話控制是多麼的糟糕。瀏覽器
若是你不瞭解 JWT,沒關係張,它並不可怕。緩存
JWT 只是用於網絡間傳遞聲明而執行一種基於 JSON 的標準。安全
例如,我是個盲人,並且聽力也很差。你上週幫我買了午飯,如今我須要你的收款帳號,把錢還給你。若是我詢問你的帳號,可是其餘人高呼他們的帳號,因爲我把別人的帳號誤認爲是你的,我可能會不當心把錢打給別人。服務器
JWT 旨在防止這種狀況發生。JWT 提供了一種簡單的方法,在彼此傳遞數據時,驗證是由誰先建立了數據。markdown
因此,像上述的例子,即便我收到了超過 100 萬個 JWT 返回的帳號信息,我也很容易能夠辨別出來哪一個真實來自於你。網絡
JWT 是 JSON 格式的被加密了的字符串。框架
JWT 的核心是密鑰,就是 JSON 數據。這是你關心的,並但願安全傳遞出去的數據。JWT 如何作到這一點,並使你信任它,就是加密簽名。svg
好比說,我寫了一封信,當我署名這封信時,意味着只要讀過這封信的人,都知道是我寫了這封信。並且個人簽名是獨一無二的,因此不會被懷疑真實性。加密簽名的方式大體相同,JWT 有兩種加密方式:對稱加密和非對稱加密,兩種方式有同等的效用。
其實,JWT 的內容(內部的 JSON 數據)一般是不加密的。這意味着,即便沒有密鑰,也能夠查看 JWT 內的數據。JWT 默認並不會加密你的數據,它只是幫助你驗證是你信任的一方建立了它。
若是你確實須要加密 JWT 內容,可使用 JWE 進行加密,但這種作法並不常見。請確保使用了正確的方法。
JWT 最多見的用途是身份驗證。有大量的 Web 安全庫使用 JWT 建立會話控制,API 令牌等。
這種作法一般是,當須要對網站/ API 進行身份驗證時,服務器生成一個包含用戶 ID 的 JWT,以及其它一些關鍵性的信息,而後再將其發送給瀏覽器/客戶端等,存儲爲會話令牌。
例如,當用戶訪問網站上的另外一個頁面時,瀏覽器會自動將該 JWT 發送到服務器,服務器驗證 JWT 確認和最初建立的令牌相同,而後容許用戶執行後續的操做。
從理論上看,還不錯,由於:
彷佛很棒,既能夠提升 Web 應用的性能,又能夠減小緩存服務器和數據庫服務器的負載,提供更好的體驗。另外你還能夠在 JWT 中存儲用戶權限信息、用戶我的信息等等更多的額外信息進一步減小數據庫壓力。
咱們已經瞭解了 JWT 如何用於身份驗證,讓咱們進入本篇的中心話題:爲何 JWT 不是最好的會話令牌,爲何普通的舊會話方式在幾乎各方面都優於 JWT。
咱們先了解一些背景知識。開發人員構建的大多數網站都相對比較簡單:
對於這類網站,要知道用戶進行交互的每一個頁面都會包含某些動態數據。好比:你正在訪問一個須要用戶登陸才能進一步操做的網站,你常常會在數據庫中對用戶進行這些操做:
咱們來看兩種方案:
若是咱們將 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 雖然對於大多數網站都沒有用,可是有幾種狀況它是頗有用的。
若是你正在構建從服務器到服務器或客戶端到服務器(如:移動應用 APP 或單頁面應用)的 API 服務,那麼使用 JWT 是很是明智的。好比:
對於這類 API 服務,JWT 很是適合,由於客戶端須要頻繁進行請求,而且權限是可控的,一般認證數據以無狀態方式持久存在,不須要過多依賴用戶信息。
若是你正在構建的應用相似單點登陸或 OpenID Connect 認證,JWT 一樣十分適合,就是實現一種經過第三方驗證用戶的方法。
當你準備構建下一個網站時,只須要使用 Web 框架默認的身份認證功能便可,不須要再集成 JWT 方式。
原文地址:https://blog.csdn.net/weixin_41153791/article/details/82291144