您現在的位置是:首頁 > 其他

李清波 2019-12-17 其他 302

JWT的優缺點以及如何去選擇?


認證 / 授權

認證(Authentication):驗證目標對象身份。比如,通過用戶名和密碼登錄某個系統就是認證。

授權(Authorization):給予通過驗證的目標對象操作權限。

更簡單地說:

認證解決了「你是誰」的問題。
授權解決了「你能做什么」的問題。


對于一般的web應用,我們知道 HTTP 是無狀態的,所以客戶端和服務端需要解決的如何讓之間的對話變得有狀態。

例如只有是登陸狀態的用戶才有權限調用某些接口,那么在用戶登陸之后,需要記住該用戶是已經登陸的狀態。(常見的方法是使用 session 機制)


常見的 session 模型是這樣工作的:

10096448-1004c3af75b0f930.webp.jpg

用戶在瀏覽器登陸之后,服務端為用戶生成唯一的 session id,存儲在服務端的存儲服務(例如 MySql, Redis)中該 session id 也同時返回給瀏覽器,以 SESSION_ID 為 KEY 存儲在瀏覽器的 cookie 中,如果用戶再次訪問該網站,cookie 里的 SESSION_ID 會隨著請求一同發往服務端服務端通過判斷 SESSION_ID 是否已經在 Redis 中判斷用戶是否處于登陸狀態

理論上來說 ,JWT 機制可以取代 session 機制。用戶不需要提前進行登陸,后端也不需要 Redis 記錄用戶的登陸信息??蛻舳说谋镜乇4嬉环莺戏ǖ?JWT, 當用戶需要調用接口時,附帶上該合法的 JWT,每一次調用接口,后端都使用請求中附帶的 JWT 做一次合法性的驗證。

這樣也間接達到了認證用戶的目的,然而JWT 真的能取代 session 機制嗎?這么做有哪些好處和壞處?

JWT 的目的不是為了隱藏或者保密數據,而是為了確保數據確實來自被授權的人創建的(不被篡改)

當你拿到 JWT 時候,你完全可以在沒有 secret 的情況下解碼出 header 和 payload,因為 header 和 payload 只是經過了 base64 編碼(encode)而已,編碼的目的在于利于數據結構的傳輸。雖然創建 signature 的過程近似于加密 (encrypt),但本質其實是一種簽名 (sign) 的行為,用于保證數據的完整性,實際上也并且并沒有加密任何數據


JWT在web應用中的缺陷

缺點一: 無法滿足注銷場景

傳統的 session+cookie 方案用戶點擊注銷,服務端清空 session 即可,因為狀態保存在服務端。但 jwt 的方案就比較難辦了,因為 jwt 是無狀態的,服務端通過計算來校驗有效性。沒有存儲起來,所以即使客戶端刪除了 jwt,但是該 jwt 還是在有效期內,只不過處于一個游離狀態。

缺點二: 無法滿足修改密碼場景

修改密碼則略微有些不同,假設號被到了,修改密碼(是用戶密碼,不是 jwt 的 secret)之后,盜號者在原 jwt 有效期之內依舊可以繼續訪問系統,所以僅僅清空 cookie 自然是不夠的,這時,需要強制性的修改 secret。

缺點二: 無法滿足token續簽場景

我們知道微信只要你每天使用是不需要重新登錄的,因為有token續簽,因為傳統的 cookie 續簽方案一般都是框架自帶的,session 有效期 30 分鐘,30 分鐘內如果有訪問,session 有效期被刷新至 30 分鐘。但是 jwt 本身的 payload 之中也有一個 exp 過期時間參數,來代表一個 jwt 的時效性,而 jwt 想延期這個 exp 就有點身不由己了,因為 payload 是參與簽名的,一旦過期時間被修改,整個 jwt 串就變了,jwt 的特性天然不支持續簽!


JWT應用場景

一次性驗證

比如用戶注冊后需要發一封郵件讓其激活賬戶,通常郵件中需要有一個鏈接,這個鏈接需要具備以下的特性:能夠標識用戶,該鏈接具有時效性(通常只允許幾小時之內激活),不能被篡改以激活其他可能的賬戶

這種場景就和 jwt 的特性非常貼近,jwt 的 payload 中固定的參數:iss 簽發者和 exp 過期時間正是為其做準備的。

總結

Web 應用中使用 JWT 是讓應用變得更復雜了。在 web 應用中,絕大多數情況下,傳統的 cookie-session 機制工作得更好。jwt 適合做簡單的 restful api 認證,頒發一個固定有效期的 jwt,降低 jwt 暴露的風險,不要對 jwt 做服務端的狀態管理,這樣才能體現出 jwt 無狀態的優勢。


評論