如今不少人使用 JWT 用做 session 管理,這是個糟糕的作法,下面闡述緣由,有不一樣意見的同窗歡迎討論。redis
首先說明一下,JWT 有兩種:算法
-
無狀態的 JWT,token 中包含 session 數據。安全
-
有狀態的 JWT,token 中僅有 session ID,session 數據仍是存儲在服務端。服務器
本文討論的是 「無狀態的 JWT」,就是把用戶的 session 數據放到 token 中。cookie
JWT 不適合作爲 session 機制,這麼作是有危險的。網絡
不少人喜歡比較 「cookies vs. JWT」,這種比較是無心義的,就像比較蘋果和桔子,cookies 是一個存儲機制,而 JWT 是加密簽名的 token,他們不是對立的,能夠一塊兒使用,或者獨立使用。session
正確的比較是「sessions vs. JWT」 和 「cookies vs. Local Storage」。併發
JWT 宣稱的優勢
人們一般會說 JWT 有以下的好處:負載均衡
- 易於水平擴展
- 簡單易用
- 加密,更安全
- 內置過時功能
- 能夠防禦 CSRF 攻擊
- 在用戶阻止了cookies後還能夠工做
對於這些所謂的好處咱們會一一剖析。高併發
(1)易於水平擴展
把 session 數據放入 JWT,服務端不須要保存 session 信息,那麼服務端天然是無狀態的,能夠隨意擴展。
看上去的確帶來了擴展上的便利,但實際上沒啥優點,服務器端保存 session 沒有任何難度:
- 多服務器場景:能夠用專門的 redis 服務器保存 session。
- 多集羣場景:多集羣間不須要共享 session,同一個用戶始終分配到同一個集羣便可。
這都是很成熟的解決方案,沒有必要在客戶端 token 中保存 session。
(2)簡單易用
看似一個小小的 token 比較簡單,實則否則,你須要本身去處理 session 的管理,怎麼可能比開箱即用的 cookies 更簡單。
(3)更安全
由於 JWT 是加密的,不少人認爲其更加安全,cookies 沒加密,不安全。
其實 cookies 只是存儲機制,你徹底可使用加密簽名的方式。
還有人認爲 cookies 沒加密會被攔截讀取。
cookies 只是 HTTP 頭信息,不負責安全,這個問題應該使用 TLS 來解決,不然,即便 JWT 也無法保證信息的安全。
(4)內置過時功能
這個功能更是沒用,是否過時應該由服務端控制,不該交給客戶端控制,不然,若是 token 被盜取,服務端將沒有任何辦法。
(5)能夠防禦 CSRF 攻擊
簡單說一下什麼是 CSRF 攻擊。
打個比方,你登陸了網銀,這時已經具有給其餘帳戶轉帳的條件了,好比轉帳的接口地址是:
http://xbank.com/transfer?to=123&money=1000
在你沒有退出網銀以前,你訪問了一個惡意網站,其中有一段代碼:
<img src=http://xbank.com/transfer?to=456789&money=1000>
這樣你就丟錢了。
這只是個樸實的例子,實際狀況比這複雜得多,但歸根結底,CSRF 攻擊就是源於:隱式身份驗證機制,就是 cookies 是自動發送給服務端的,沒法保證該請求是用戶批准的。
因此,不少人就認爲使用 JWT 就沒這個問題了,由於不用 cookies 了。
那麼請問,你是把 JWT 保存在哪裏的?有2個保存方式:
- cookie:這樣一樣會面臨 CSRF 攻擊。
- 其餘地方,例如 Local Storage:這樣的確避免了 CSRF,但暴露了更嚴重的安全問題,Local Storage 這類的本地存儲是能夠被 JS 直接讀取的。
其實,防禦 CSRF 攻擊的正確方式只有:CSRF token。
(6)在用戶阻止了cookies後還能夠工做
不幸的是,在用戶阻止了 cookies 的場景中,一般不只僅是阻止 cookies,而是阻止全部的本地存儲,包括 Local Storage。
這樣的話,JWT 也一樣沒法工做。
JWT 的缺點
(1)體積大
若是把 session 信息編碼後放入 token,那麼其體積會很大,頗有可能超出 cookie 的大小限制,那就只能把 JWT 保存在 Local Storage 了,也就產生了安全問題。
並且,體積大,網絡壓力就大了。
(2)不安全
這個問題上面分析過了,若是放在 cookie 裏,那和傳統的 session 方案就差很少了,若是放在別的地方,就有其餘安全問題了。
(3)沒法使某個 JWT 無效
不像 session,在服務端可使其失效,而 JWT 直到其過時才能無效。
好比服務端檢測到了一個安全威脅,也沒法使相關的 JWT 失效。
也就是說,當你發現風險時,沒法殺死某個 session,若是你想解決這個問題,就須要服務端能夠對 session 進行管理,那麼就變回有狀態的模式了。
(4)session 數據舊了
session 數據是保存在 JWT 中的,其中會有用戶的相關信息,例如角色。
在 JWT 過時以前,用戶的角色發生了變化,那麼這時 JWT 中的信息就是舊的了,由於沒法更新。
小結
JWT 真的不適合當作 session 使用,JWT 更適合一次性的命令認證,設置一個很短的有效期。
本文的目的不是說 JWT 很差,而是想說把 JWT 用做 session 是用錯了地方。
你是怎麼使用 JWT 的?歡迎交流討論。
翻譯整理自: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
推薦閱讀: