繁體中文(香港)
  • jwt
  • auth
  • authentication
  • identity
  • api
  • openid
  • oauth

JSON Web Token (JWT) 是什麼?

在 5 分鐘內清楚了解 JSON Web Token (JWT) 的基本知識。

Gao
Gao
Founder

JSON Web Token (JWT) 廣泛應用於現代網絡應用程式和開放標準例如 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。在我們的例子中,algHS256,代表 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 哈希函數創建的。你還可以使用 RS384RS512 來創建帶有 SHA384 和 SHA512 哈希函數的簽名。

簽名是用私鑰創建的:

我們可以再次組裝這些部分來創建一個 JWT,最終的 JWT 如下所示:

現在,客戶端可以在不知道私鑰的情況下驗證簽名。

ECDSA

雖然 RSA 被廣泛採用,但它受到較大簽名尺寸的影響,有時超過標頭和載荷的合併尺寸。橢圓曲線數字簽名算法(ECDSA)是另一種非對稱算法,可以創建更緊湊的簽名,而且效能更高。

要為 ECDSA 生成私鑰,我們需要選擇一個曲線。這超出了這篇文章的範疇,但你可以在這裡找到更多信息。

ECDSA 的標頭 JSON 如下所示:

ES256 代表 ECDSA-SHA256,這意味著簽名是用 ECDSA 算法和 SHA256 哈希函數創建的。你也可以使用 ES384ES512 來創建帶有 SHA384 和 SHA512 哈希函數的簽名。

簽名是用私鑰創建的:

最終的 JWT 保持與 RSA 相同的結構,但具有顯著縮短的簽名:

驗證 JWT

驗證 JWT 非常簡單,是創建 JWT 的逆過程:

  1. 使用 . 分隔符將 JWT 拆分為三個部分(標頭、載荷和簽名)。
  2. 使用 Base64URL 解碼標頭和載荷。
  3. 使用標頭中指定的算法和公鑰(對於非對稱算法)驗證簽名。

有許多可用的庫可以幫助進行 JWT 驗證,例如適用於 Node.js 和網頁瀏覽器的 jose

總結

在這篇文章中,我們簡要地解釋了 JWT 的核心概念,以及如何創建和驗證它的概覽。許多細節尚未被探索,我們會在未來的文章中覆蓋它們。

Logto 利用像 JWT 和 OpenID Connect 的開放標準來通過簡化的工作流程保護你的應用程式和 API。若你感興趣,可以免費試用(不需要信用卡)。