JSON Web Token (JWT) 是什麼?
在 5 分鐘內清楚理解 JSON Web Token (JWT) 的基本概念。
JSON Web Token (JWT) 在現代 web 應用程式和開放標準(如 OpenID Connect)中被廣泛使用,用於促進驗證和授權。雖然官方 RFC 7519 是一個重要的參考資料,但對初學者來說可能很難理解。在本文中,我們將專注於 JWT 的核心概念,並用簡單的語言和範例來呈現。
為什麼需要 JWT?
如今,在兩方之間使用 JSON 來交換數據已經相當常見。考慮一個表示使用者的 JSON 物件:
sub
是 "subject" 的縮寫,在 OpenID Connect 中是一個 標準聲明,用於表示用戶標識符(用戶 ID)。
我們如何保證這個 JSON 物件的 完整性?換句話說,我們如何確保數據在傳輸過程中沒有被篡改?一個常見的解決方案是使用數字簽名。例如,我們可以使用 公鑰加密:伺服器用它的私鑰對 JSON 物件進行簽名,客戶端可以用伺服器的公鑰驗證該簽名。
簡而言之,JWT 提供了一種標準化的方法來表示 JSON 物件及其簽名。
JWT 的格式
由於用於創建數字簽名的算法有很多種,因此有必要指定用於 JWT 簽名的算法。這是透過構建一個 JSON 物件來完成的:
alg
是 "algorithm" 的縮寫,typ
是 "type" 的縮寫。
通常,typ
被設定為大寫的 JWT
。在我們的範例中,alg
是 HS256
,代表 HMAC-SHA256(我們稍後會解釋),表示我們正在使用這個算法來創建簽名。
現在,我們擁有了創建 JWT 的所有要素:
- 標頭 JSON:算法和類型
- 載荷 JSON:實際數據
- 簽名:涵蓋標頭和載荷的簽名
然而,某些字符如空格和換行符對網路傳輸不友好。因此,標頭和載荷需要進行 Base64URL 編碼。典型的 JWT 看起來像這樣:
.
用作分隔符。
讓我們把所有部分組合起來創建一個 JWT:
標頭
JSON: {"alg":"HS256","typ":"JWT"}
Base64URL 編碼: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
載荷
JSON: {"sub":"foo","name":"John Doe"}
Base64URL 編碼: eyJzdWIiOiJmb28iLCJuYW1lIjoiSm9obiBEb2UifQ
簽名
在 HMAC-SHA256 中,簽名是用密鑰創建的:
例如,密鑰是 some-great-secret
,簽名就成為:XM-XSs2Lmp76IcTQ7tVdFcZzN4W_WcoKMNANp925Q9g
。
JWT
最終的 JWT 是:
任何擁有密鑰的一方都可以驗證這個有效的 JWT。
選擇簽名算法
如前所述,用於創建數字簽名的算法有多種。我們使用了 HS256
作為範例,但它可能不夠強,因為密鑰必須在雙方之間共享(例如,客戶端和伺服器)。
在現實場景中,客戶端可能包括像 React 應用這樣的公眾應用,這些應用無法保證密鑰的安全。因此,首選的方法是使用公鑰加密(即非對稱加密)來簽署 JWT。讓我們從最受歡迎的算法開始:RSA。
RSA
RSA 是一種非對稱算法,它使用一對密鑰:一個公鑰和一個私鑰。公鑰用來驗證簽名,私鑰用來簽名。
RSA 的標頭 JSON 如下所示:
RS256
代表 RSA-SHA256,表示簽名是使用 RSA 算法和 SHA256 哈希函數創建的。你還可以使用RS384
和RS512
來創建使用 SHA384 和 SHA512 哈希函數的簽名。
簽名是用私鑰創建的:
同樣,我們可以組合這些部分來創建一個 JWT,最終的 JWT 看起來像這樣:
現在,客戶端可以在不知道私鑰的情況下驗證簽名。
ECDSA
儘管 RSA 被廣泛採用,但它的簽名大小較大,有時甚至超過標頭和載荷的總大小。橢圓曲線數字簽名算法(ECDSA)是另一種非對稱算法,可以創建更緊湊的簽名,並且效能更高。
要為 ECDSA 生成私鑰,我們需要選擇一個曲線。這超出了本文的範疇,但你可以在 這裡 找到更多資訊。
ECDSA 的標頭 JSON 如下所示:
ES256
代表 ECDSA-SHA256,表示簽名是使用 ECDSA 算法和 SHA256 哈希函數創建的。你還可以使用ES384
和ES512
來創建使用 SHA384 和 SHA512 哈希函數的簽名。
簽名是用私鑰創建的:
最終的 JWT 保留了與 RSA 相同的結構,但簽名顯著縮短:
驗證 JWT
驗證 JWT 是創建 JWT 的逆過程,簡單明瞭:
- 使用
.
分隔符將 JWT 分為三部分(標頭、載荷和簽名)。 - 使用 Base64URL 解碼標頭和載荷。
- 使用標頭中指定的算法和公鑰(對於非對稱算法)驗證簽名。
有許多庫可以協助 JWT 驗證,比如用於 Node.js 和 Web 瀏覽器的 jose。
結論
在本文中,我們簡要說明了 JWT 的核心概念,以及如何創建和驗證它的概覽。 仍有許多細節尚未探討,我們將在未來的文章中覆蓋這些內容。
Logto 利用 JWT 和 OpenID Connect 等開放標準透過簡化的工作流程來保護你的應用程式和 API。 如果你有興趣,可以試用免費版本(不需要信用卡)。