以前我覺得成績不重要。清華 、北大、複旦、交大 ,隻能代表學生時代的成就。後來我發現,努力是種習慣,它會貫穿終生
介紹
JWT的全稱是Json Web Token。将使用者資訊加密到token裡,伺服器不儲存任何使用者資訊,隻儲存密鑰資訊,通過使用特定加密算法驗證token,通過token驗證使用者身份。jwt 之前,使用 session 來做使用者認證,那我們先看看傳統的session機制
cookie-session機制原理
- 使用者浏覽器通路web網站,輸入使用者名密碼
- 伺服器校驗使用者名密碼通過之後,生成sessonid并把sessionid和使用者資訊映射起來儲存在伺服器
- 伺服器将生成的sessionid傳回給使用者浏覽器,浏覽器将sessionid存入cookie
- 此後使用者對該網站發起的其他請求都将帶上cookie中儲存的sessionid
- 服務端把使用者傳過來的sessionid和儲存在伺服器的sessionid做對比,如果伺服器中有該sessionid則代表身份驗證成功
cookie-session機制缺點
- 代碼安全機制不完善,可能存在CSRF漏洞
- 服務端需要儲存sessionid與用戶端傳來的sessionid做對比,如果是分布式部署,需要複制sessionid,在多台叢集機器之間共享
- 如果需要單點登入,則須将sessionid存入redis等外部存儲保證每台機器每個系統都能通路到,如果外部存儲服務當機,則單點登入失效
jwt的驗證過程
- 使用者通路網站,輸入賬号密碼登入
- 伺服器校驗通過,生成JWT,不儲存JWT,直接傳回給用戶端
- 用戶端将JWT存入cookie或者localStorage
- 此後使用者發起的請求,都将使用js從cookie或者localStorage讀取JWT放在http請求的header中,發給服務端
- 服務端擷取header中的JWT,用base64URL算法解碼各部分内容,并在服務端用同樣的秘鑰和算法生成signature,與傳過來的signature對比,驗證JWT是否合法
由于服務端不儲存使用者資訊,不用做sessonid複制,這樣叢集水準擴充就變得容易了。同時使用者發請求給服務端時,前端使用JS将JWT放在header中手動發送給服務端,服務端驗證header中的JWT字段,而非cookie資訊,這樣就避免了CSRF漏洞攻擊
jwt由三個部分組成:header.payload.signature
header部分
header部分最常用的兩個字段是alg和typ,alg指定了token加密使用的算法(最常用的為HMAC和RSA算法),typ`聲明類型為JWT
header通常會長這個樣子:
{
"alg" : "HS256",
"typ" : "jwt"
}
payload部分
payload則為使用者資料以及一些中繼資料有關的聲明,用以聲明權限,舉個例子,一次登入的過程可能會傳遞以下資料。
{
"user_role" : "finn", //目前登入使用者
"iss": "admin", //該JWT的簽發者
"iat": 1573440582, //簽發時間
"exp": 1573940267, //過期時間
"nbf": 1573440582, //該時間之前不接收處理該Token
"domain": "example.com", //面向的使用者
"jti": "dff4214121e83057655e10bd9751d657" //Token唯一辨別
}
signature部分
signature的功能是保護token完整性。
生成方法為将header和payload兩個部分聯結起來,然後通過header部分指定的算法,計算出簽名。
Jwt攻擊總結一下
- 背景未校驗簽名 解碼後換内容再編碼
- 禁用哈希 算法修改為none
- 暴破弱密鑰
- 操縱Key ID 原因是key ID 裡的内容可能被作為參數進資料庫或者查詢 (SQL注入、目錄周遊、指令注入)
說說常用的爆破攻擊
前提條件 :
- 知悉JWT使用的加密算法
- 一段有效的、已簽名的token
- 簽名用的密鑰不複雜(弱密鑰)
其他推薦
爆破工具:https://github.com/brendan-rius/c-jwt-cracker
解碼該JWT token: https://jwt.io/
