JWT 鑑權
JWT 是什麼
JSON Web Token(JWT)是一個開放式標準(RFC 7519),它定義了一種緊湊且自包含的方式,用於在各方之間以JSON物件安全傳輸資訊。這些資訊可以通過數字簽名進行驗證和信任。
JWT 的組成
JWT 的格式為 xxx.yyy.zzz。
包含 Header(頭部),Payload(負載),Signature(簽名)三部分。
-
Header
通常會宣告使用的加密演算法和token型別
{ "alg": "HS256", "typ": "JWT" }
-
Payload
Payload 包含 Claims,Claim是一些實體(一般都是使用者)的狀態和額外的資料組成。
JWT 為我們預定義了一些 Claims,例如:iss (issuer), exp (expiration time), sub (subject), aud (audience), andofollow,noindex">others .
但是並不要求我們強制使用,我們也可以根據需求自定義 Claim
{ "sub": "1234567890", "name": "Taven", "admin": true }
- Signature
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
這段虛擬碼已經很好的講解了,簽名是如何計算的。服務端提供一個secret,將header、payload 進行base64編碼,然後使用header中宣告的演算法計算簽名。
JWT 與 傳統session 對比
- 效能:JWT 輕量級,而session 會佔用大量服務端記憶體;
- 部署:使用session的系統 負載均衡需要考慮 session 共享,而JWT 不需要;
- 安全:安全性的話,小弟不敢多說,我覺得五五開吧,有人說 JWT 洩露的話,直接就可以登入了。但是使用 session 如果請求被攔截了都是一樣的;
- 場景:APP 中由於沒有cookie吧,多是使用token。而 web 應用的話,使用 token 和 session 都是可以的。
實現思路
簡單一句話就是,登入之後服務端給客戶端頒發JWT,客戶端將 JWT 放在請求頭中,服務端 filter 校驗http header中的JWT。
查閱了一些資料後發現一些分歧
-
方案1: 有的朋友認為服務端不需要儲存 JWT,只在 filter 校驗的時候解析無誤,即認為 JWT 是可用的。在需要重置 JWT 的時候(例如登出),客戶端主動刪除JWT。這種做法引發的問題,例如在登出了之後,token 依然可用,由於服務端沒有儲存 token,無法去校驗。於是乎有了方案2
-
方案2:服務端資料庫中儲存 JWT,filter 每次校驗 token 與資料庫中是否一致,這種做法雖然穩妥,但是在效能上一定是不如方案1的。
demo :https://gitee.com/yintianwen7/taven-springboot-learning/tree/master/spring-boot-jwt