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