了解 JWT、OAuth 和 Bearer 令牌
當(dāng) Web 成為人們可以實(shí)際執(zhí)行有意義的任務(wù)(如銀行或工作)的地方時(shí),隱含的需求就是對(duì)使用服務(wù)的人進(jìn)行身份驗(yàn)證。
畢竟,我們不能只相信使用這些服務(wù)的人使用了它們。必須實(shí)施某種方式,讓人們可以證明他們是他們所說(shuō)的那個(gè)人。
最初,這就像用戶名和密碼組合一樣簡(jiǎn)單。理論上,您是唯一知道您的密碼的人。
身份鑒權(quán)
通常,您會(huì)使用您的憑證在網(wǎng)頁(yè)上填寫表單,然后點(diǎn)擊提交。您的詳細(xì)信息將通過(guò) HTTP 發(fā)送 POST 請(qǐng)求到服務(wù)器,服務(wù)器將檢查您的密碼是否與存檔的內(nèi)容匹配,然后向您發(fā)放一個(gè) cookie。
該 Cookie 將包含您的Token,并將與每個(gè)后續(xù)請(qǐng)求一起提交,以便服務(wù)器知道在每個(gè)后續(xù)請(qǐng)求中信任您。
如果需要在會(huì)話期間存儲(chǔ)數(shù)據(jù),例如您選擇的數(shù)據(jù)或首選項(xiàng),則可以將其存儲(chǔ)在session中。有時(shí),這被稱為 sessionizing 您的數(shù)據(jù)。
在用戶session中存儲(chǔ)數(shù)據(jù)是存儲(chǔ)和檢索瞬態(tài)信息的一種簡(jiǎn)單且廉價(jià)的方法。
不幸的是,這種方法有幾個(gè)缺點(diǎn):
- 將您的用戶名和密碼發(fā)布到服務(wù)器,經(jīng)常發(fā)生在不安全的 HTTP 請(qǐng)求上。在這種情況下,您的用戶名和密碼可以被任何人或您與服務(wù)器之間的任何內(nèi)容直接從 HTTP的POST 請(qǐng)求中讀出
- 將您的密碼(本應(yīng)是秘密的)發(fā)送到遠(yuǎn)程服務(wù)器并不是一個(gè)好主意。如果遠(yuǎn)程服務(wù)器遭到入侵,那么不良行為者將可以輕松訪問(wèn)發(fā)送給他們的這些憑據(jù),然后可以自由地在其他銀行網(wǎng)站或電子郵件提供商上試用這些憑據(jù)。因?yàn)槊艽a經(jīng)常被重復(fù)使用,所以這將非常有效
- 很多時(shí)候,密碼會(huì)以明文形式存儲(chǔ),并以這種格式在服務(wù)器上進(jìn)行比較,這對(duì)于黑客或其他可以檢索用戶名/密碼組合寶庫(kù)的不良行為者來(lái)說(shuō)顯然是一個(gè)相當(dāng)大的蜜罐
至于在用戶的session中存儲(chǔ)數(shù)據(jù),如果有一臺(tái)服務(wù)器為應(yīng)用程序提供服務(wù),則此方法有效。當(dāng)服務(wù)器跨越多個(gè)服務(wù)器時(shí),所有服務(wù)器都必須保持其會(huì)話同步。
為此,人們?cè)O(shè)計(jì)了許多方法,例如將會(huì)話數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)庫(kù)服務(wù)器上或某種內(nèi)存存儲(chǔ)中,但從長(zhǎng)遠(yuǎn)來(lái)看,更好的解決方案是簡(jiǎn)單地完全刪除會(huì)話。
依賴服務(wù)器上的可變數(shù)據(jù)存儲(chǔ)不是一個(gè)好主意,理想情況下,使用者應(yīng)該擁有應(yīng)用程序運(yùn)行所需的所有信息。
JWT
回到我們最初的例子,當(dāng)我們看另一個(gè)人時(shí),我們可以快速評(píng)估我們是否認(rèn)識(shí)他們。根據(jù)我們是否了解他們,我們可以向他們提供有關(guān)我們生活和發(fā)生的事情的更多細(xì)節(jié)。
但我們不能指望總是能夠看到信任他們的人。有時(shí),我們可以在不見對(duì)方的情況下進(jìn)行信任交換。
例如,當(dāng)您上班時(shí),您可能有一張刷卡,您可以在讀卡器上刷卡。讀卡器會(huì)讀取您的卡,如果卡有效,則通過(guò)身份驗(yàn)證。這更好,因?yàn)槟槐叵蛉魏稳送嘎赌拿艽a或任何對(duì)您來(lái)說(shuō)保密的事情。
我們知道使用讀卡器進(jìn)入建筑物是安全的,因?yàn)樾湃捂準(zhǔn)峭暾?。讀卡器是由值得信賴的公司發(fā)行的,您的門禁卡也可能由他們發(fā)行。我們可以把卡帶走,在某個(gè)地方存放很長(zhǎng)時(shí)間,當(dāng)我們回來(lái)的時(shí)候,它仍然是值得信賴的。
如果有人打開卡并更改或更改它以試圖給他們更多的訪問(wèn)權(quán)限,他們反而會(huì)損壞卡,它就會(huì)停止工作。
JWT 有點(diǎn)像這樣。它們由三個(gè)獨(dú)立元件組成:
- 描述令牌中的信息以及正在使用的加密的標(biāo)頭
- payload
- 證明 Token 可靠的簽名
計(jì)算簽名的算法是 header 和 payload 的加密結(jié)果與 secret 相結(jié)合。因此,如果header或payload發(fā)生更改,則簽名將無(wú)效,并且內(nèi)容將不受信任。
因此,即使我們?cè)?JWT 中包含數(shù)據(jù)以表明用戶是管理員,只要簽名得到正確驗(yàn)證,我們就可以確保 JWT 仍然是該事實(shí)的正確表示。因?yàn)楣姛o(wú)法訪問(wèn)我們的簽名密鑰,所以我們可以確定唯一可以頒發(fā)該 JWT 的實(shí)體是我們的服務(wù)器。
我們可以在 https://jwt.io 這樣的網(wǎng)站上輕松查看 JWT 令牌的內(nèi)容。

攜帶您的令牌
現(xiàn)在我們有了令牌,下一個(gè)問(wèn)題應(yīng)該是我們?nèi)绾螌⑵涑尸F(xiàn)給服務(wù)器。以前的身份驗(yàn)證方法需要基于 Cookie 的身份驗(yàn)證。但是,通常使用我們的 JWT 令牌,我們會(huì)將它們與受保護(hù)的資源一起呈現(xiàn)給服務(wù)器,以便我們可以被授予訪問(wèn)權(quán)限。
這意味著在我們的 HTTP 方法(POST、GET 等)中,我們還將包含一個(gè) Authorization 值。它通常如下所示:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.uXrIhrveuvbR4tD1ULholQObboLVC-wIfJOEVElEzcs
使用此令牌,服務(wù)器可以在分析令牌中的聲明之前驗(yàn)證令牌。但是,索賠包含哪些內(nèi)容?
聲明只是 JWT 中包含特定令牌信息的字段。它們分為三類:注冊(cè)、公共和私有。
已注冊(cè)的聲明是可在 JWT 令牌中使用的標(biāo)準(zhǔn)字段。它們不是必需的,但通常會(huì)在大多數(shù)代幣中找到。
公共聲明由應(yīng)用程序定義,并與正在使用的應(yīng)用程序的數(shù)據(jù)相關(guān)。
私有聲明是用于在實(shí)現(xiàn)之間共享信息的自定義聲明,但只有涉及的實(shí)體知道聲明是什么以及它們的工作原理。
OAuth 2.0 與此有何關(guān)系?
我們?cè)敿?xì)介紹了什么是 JWT、它們的工作原理以及我們可以信任它們的原因。通常,它們與 OAuth 一起被提及,有時(shí)人們會(huì)嘗試比較它們或嘗試選擇一個(gè)而不是另一個(gè)。
但是,它們沒有可比性,而是 OAuth 通常使用 JWT 令牌來(lái)傳輸與其相關(guān)的信息。由于 JWT 是一種以防篡改方式傳輸重要數(shù)據(jù)的可靠方法,因此它們是在 OAuth 2 中使用的不錯(cuò)選擇。
例如,OAuth 發(fā)送的 ID 令牌始終作為 JWT 發(fā)送。當(dāng)同時(shí)發(fā)送訪問(wèn)令牌時(shí),它通常也作為 JWT 發(fā)送。OAuth 使用 JWT 來(lái)實(shí)現(xiàn)與其相關(guān)的各種流。
另一種類型的令牌是 Bearer 令牌,它與 Authorization 標(biāo)頭中的每個(gè) HTTP 方法一起發(fā)送。它充當(dāng)安全資源,指示令牌的持有者有權(quán)訪問(wèn)相關(guān)資源。因此,請(qǐng)務(wù)必僅將 Bearer 令牌發(fā)送到需要它的受保護(hù)終端節(jié)點(diǎn)。
OAuth 可以使用任何其他可行的系統(tǒng)來(lái)傳輸其令牌,但是因?yàn)?JWT 是一個(gè)標(biāo)準(zhǔn),所以這就是正在使用的系統(tǒng)。事實(shí)上,OpenID Connect 正在擴(kuò)展 JWT。
結(jié)論
JWT 和 OAuth 是安全的異步 Web 的關(guān)鍵部分。正如我們?cè)诒疚闹兴吹降模麄儾皇歉?jìng)爭(zhēng)對(duì)手,您也不應(yīng)該(或您可以)選擇一個(gè)而不是另一個(gè)。JWT 以 OAuth 的補(bǔ)充能力存在,并且在將可信數(shù)據(jù)從 A 點(diǎn)移動(dòng)到 B 點(diǎn)方面做得非常出色。






























