JWT 介绍 - Step by Step
翻譯自 Mohamad Lawand 2021年3月11日的文章?《Intro to JWT - Step by Step》?[1]
在本文中,我將向您介紹?JWT[2]。
我們今天要講的內(nèi)容包含:
JWT 是什么
我們應(yīng)該在什么時候使用它
JWT 與 Session Id 比較
JWT 結(jié)構(gòu)
JWT 簽名
JWT 是什么
JWT (JSON Web Token) 是一個開放標準[3],它定義了一種以緊湊和自包含的方法,用于在雙方之間安全地傳輸編碼為 JSON 對象的信息。
因此,簡單來說,它是 JSON 格式的加密字符串,其中包含敏感信息,它使我們能夠驗證不同服務(wù)間的發(fā)送者。
應(yīng)該在什么時候使用 JWT?
授權(quán):?這是使用 JWT 最常見的場景。JWT 用于授權(quán)而非身份驗證。通過身份驗證,我們驗證用戶名和密碼是否有效,并將用戶登錄到系統(tǒng)中。通過授權(quán),我們可以驗證發(fā)送到服務(wù)器的請求是否屬于通過身份驗證登錄的用戶,從而可以授予該用戶訪問系統(tǒng)的權(quán)限,繼而批準該用戶使用獲得的 token 訪問路由、服務(wù)和資源。
信息交換:?JSON Web Token 是在雙方之間安全地傳輸信息的一種好方法。因為 JWT 可以被簽名(例如,使用公鑰/私鑰對),所以使您能確保發(fā)送方是他們所聲稱的那一方。此外,由于簽名是使用 Header 和 Payload 計算的,因此還使您能驗證發(fā)送的內(nèi)容沒有被篡改。
JWT 與 Session Id 比較
§小型 Web 應(yīng)用程序
Session Id 實現(xiàn)
在傳統(tǒng)的 Web 應(yīng)用程序中,我們使用 Session 來授權(quán)用戶,當(dāng)用戶登錄到應(yīng)用程序后,我們會為該用戶分配一個唯一的 Session Id。我們將此 Session Id 保存在用戶瀏覽器的安全 cookie 中和服務(wù)器的內(nèi)存中。我們對每個請求都使用相同的會話,以便服務(wù)器知道該用戶已通過身份驗證。對于每個請求,cookie 中的 Session Id 都會與服務(wù)器內(nèi)存中的 Session Id 作匹配,以驗證用戶是否被授權(quán)。
JWT 實現(xiàn)
在 JWT 實現(xiàn)中,我們使用 JWT 授權(quán)用戶,當(dāng)用戶登錄到應(yīng)用程序后,就會為每個通過身份驗證的用戶生成一個唯一的 JWT。我們將該 token 保存在瀏覽器的 local storage 或者 cookie 中,而不會在服務(wù)器端保存任何內(nèi)容。對于每個請求,該 token 都會被發(fā)送到服務(wù)器進行解密和驗證,以核實該用戶是否已授權(quán),不管以何種方式篡改了 token 都會被拒絕。
這種實現(xiàn)對于小型站點來說很好,僅僅因為我們不再存儲 Session Id,從而通過減少服務(wù)器的負載,我們已經(jīng)從 JWT 中看到了一些好處。
§高級 Web 應(yīng)用程序(多個服務(wù)器)
如果我們的應(yīng)用程序越來越受歡迎,需要我們對其進行擴展,會發(fā)生什么呢?
Session Id 實現(xiàn)
我們需要有一臺連接到負載均衡器的新服務(wù)器,以便基于流量和可用性在 Web 服務(wù)器之間導(dǎo)航流量。這種實現(xiàn)給我們帶來了一個新的問題,如下所示:
如果用戶 1?登錄到了服務(wù)器 1,那么服務(wù)器 1?已經(jīng)將 session 保存在其內(nèi)存中,當(dāng)用戶 1?發(fā)出另一個請求并且負載均衡器將該請求重定向到了服務(wù)器 2,而服務(wù)器 2?沒有保存該 session 信息,這時會發(fā)生什么情況?
用戶將被認為已退出應(yīng)用程序并被要求再次登錄,這不是一個好的用戶體驗。通常,我們解決這個問題的方法是引入緩存:
現(xiàn)在,所有的 Session 也將同時保存在緩存中,因此任何一臺服務(wù)器都可以檢查該 Session 是否存在,并可以利用它來驗證用戶并授予他們對應(yīng)用程序的訪問權(quán)限。
盡管緩存解決了我們的問題,但是在生產(chǎn)環(huán)境中,這種解決方案有著昂貴的成本:
需要大量的 RAM、CPU、存儲來跟蹤所有這些會話和平穩(wěn)地處理請求
需要維護緩存,以確保沒有幽靈會話或無效會話
萬一某臺服務(wù)器崩潰,所有未與緩存同步的會話都會丟失
使用戶無效更復(fù)雜
托管成本高
JWT 實現(xiàn)
讓我們來看看如何通過 JWT 實現(xiàn)來處理相同的情況。
不同于在 Cookie 中使用 Session Id 與服務(wù)器內(nèi)存中的 Session 作匹配;我們可以使用 JWT 來代替它。此時,當(dāng)用戶登錄到我們的應(yīng)用程序時,服務(wù)器將不會生成 Session Id 并將其保存在內(nèi)存中,而是會創(chuàng)建一個 JWT token,并對其進行編碼和序列化,然后使用自己的加密機制對其進行簽名。通過這種方式,服務(wù)將知道一旦對它做了變更或篡改,便將其變?yōu)闊o效。由于通過服務(wù)器的加密機制對其進行了簽名,所以這是可以被檢驗的。
使用 JWT 可以更容易地管理可伸縮性,因為我們不需要服務(wù)器來處理任何會話檢查或緩存檢查。請求可以轉(zhuǎn)發(fā)到負載均衡器為其分配的任一服務(wù)器,而無需擔(dān)心會話的可用性。萬一某臺服務(wù)器宕機,所有的 token 將仍然有效,因為所有服務(wù)器上的加密機制是一樣的。
§JWT 和 Session Id 的區(qū)別總結(jié)
讓我們來快速總結(jié)一下 JWT 和 Session Id 的區(qū)別
JWT
服務(wù)器上不保存任何東西,JWT 存儲于客戶端中
由服務(wù)器加密和簽名
token 包含用戶的所有信息
所有信息都存儲于 token 本身中
易于縮放
Session Id
Session Id 保存于服務(wù)器和客戶端中
加密并簽名
Session Id 是對用戶的引用
服務(wù)器需要查找用戶并進行必要的檢查
難以縮放
JWT 結(jié)構(gòu)
JSON Web Token 由三部分組成,以點(.)分隔,分別是:
Header(標頭)
Payload(有效負載)
Signature(簽名)
因此,JWT 通常如下所示:
xxxxxx.yyyyyyy.zzzzzzzz這種分隔使從視覺上更容易看出 token 的不同部分。讓我們來分解一下它的不同的部分。
§Header
Header 通常由兩部分組成:
token 的類型,這里是 JWT
使用的簽名算法,比如 HMAC、SHA256 或 RSA。
例如:
{"alg": "HS256","typ": "JWT" }然后,將此 JSON 以?Base64Url?編碼,形成 JWT 的第一部分。
§Payload (Data)
token 的第二部分是有效負載,其中包含 Claims(聲明)。Claims 是有關(guān)實體(通常是用戶)和其他數(shù)據(jù)的聲明。有三種類型的 Claims:registered、public 和 private claims。
Registered Claims:這是一組非強制性的但建議使用的預(yù)定義 Claims,以提供一組有用的、可互操作的 Claims。其中包含:iss?(issuer,簽發(fā)者)、exp?(expiration time,過期時間)、sub?(subject,主題)、aud?(audience,受眾) 等等。
Public Claims:這些可以由使用 JWT 的人員隨意定義。但是為了避免沖突,應(yīng)該在 IANA JSON Web Token Registry 中定義它們,或者將其定義為包含抗沖突命名空間的 URI。
Private Claims:這些是自定義聲明,是為了在同意使用它們的雙方共享信息而創(chuàng)建的,它們既不是注冊的聲明,也不是公共的聲明。
舉一個有效負載的例子:
{"sub": "221122112","name": "Mohamd Lawand","admin": true,"exp": 15323232,"iat": 14567766 // 該 token 的簽發(fā)時間 }然后,對有效負載進行?Base64Url?編碼,形成 JSON Web Token 的第二部分。
除非將其加密,否則請不要將機密信息放入 JWT 的 Payload 或 Header 元素中。
簽名
簽名使我們能夠驗證 token 是否有效和沒被篡改。它的工作方式是獲取 token 的前兩部分,將 Header 和 Payload 分別編碼為 Base64,然后將它們用 “.” 連接起來。這樣我們就擁有了與用戶共享的所有數(shù)據(jù)。
然后,獲取在第一部分(Header)中提供的算法并應(yīng)用于上面的連接結(jié)果。如果前兩部分的哈希結(jié)果與 token 的第三部分匹配,則表示此 JWT 是有效的;如果不匹配,則表示此 token 被修改過,是無效的。
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)這種方案的唯一威脅是密鑰在服務(wù)器以外的任何地方都可用。但是,如果我們保護好密鑰的安全,就沒有什么能損害這一過程。
簽名被用于驗證消息在傳輸過程中沒有被篡改,而且,當(dāng) token 是使用私鑰簽名時,它還可以驗證 JWT 發(fā)送方的真實身份。
它的工作原理與密碼哈希非常相似——我們將兩部分組合在一起,并且使用特定的算法進行單向哈希,然后我們比較哈希的結(jié)果看它們是否有效。
§簽名方式
現(xiàn)在,讓我們來看一下對 JWT 進行簽名的方式:
一個 secret(使用 HMAC 算法)
一個 公鑰/私鑰對(使用 RSA 或 ECDSA)
簽名的 token 可以驗證其中包含的 Claims 的完整性,而加密的 token 則可以向其他方隱藏這些 Claims。
相關(guān)鏈接:
https://dev.to/moe23/intro-to-jwt-mcb?Intro to JWT - Step by Step???
https://jwt.io/?jwt.io???
https://tools.ietf.org/html/rfc7519?RFC 7519???
作者 :Mohamad Lawand
譯者 :技術(shù)譯民
出品 :技術(shù)譯站(https://ITTranslator.cn/)
總結(jié)
以上是生活随笔為你收集整理的JWT 介绍 - Step by Step的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 读写Ini文件
- 下一篇: 程序员过关斩将--重复的请求并不好过滤