JWT 是什麼?一次搞懂 JWT 的組成和運作原理

古古

2024/12/17


在現今的架構中,JWT 可以說是使用非常廣泛的一項技術,所以這篇文章我們就來介紹一下 JWT 是由哪些部分所組成,以及每個部分所負責的功能為何吧!

本文為 JWT 系列文之一,建議在閱讀本文前,要先了解 Session 和 JWT 之間的差別、以及 Encode/Decode 的概念,才會比較好上手。如果你對這些概念還不太熟悉,也可以參考前面的文章介紹(建議按照順序閱讀,才會有最佳的閱讀體驗):

  1. Session 和 JWT 的差別在哪裡?
  2. 密碼學中的 Encode、Encrypt、Hash 的差別在哪裡?
  3. JWT 是什麼?一次搞懂 JWT 的組成和運作原理 (本文)
  4. JWT 是如何實作「數位簽名」的?揭秘 signature 的面紗

回顧:Session 和 JWT 的差別 #

Session 和 JWT 的差別在哪裡? 的文章中,我們有介紹到 Session 和 JWT 的差別分別是:

  • Session 認證: 將登入的資訊儲存在「後端 Server」上
  • JWT 認證: 將登入的資訊儲存在「前端 Client」中

所以大家就可以根據自己的需求,選擇到底要使用 Session 來進行認證、還是使用 JWT 進行認證。

不過在當時的那篇文章中,我們先跳過了「為什麼後端可以無條件相信 JWT 中的內容?」的相關細節,因此這篇文章就會回過頭來介紹這部分,了解 JWT 中的組成有哪些,以及 JWT 的運作原理是什麼,使得後端可以無條件相信 JWT 中所記錄的資訊。

什麼是 JWT? #

所謂的 JWT,他的全稱是 JSON Web Token,而他的用途,通常就是用來「傳遞身份認證的數據」。

在 JWT 中,會由三個部分所組成,分別是:header、payload 以及 signature,並且在每一個部分之間,就會使用一個 . 作為分隔。

像是在下面的例子中,左邊的 eyJhb.... 這段亂碼,他其實就是一個 JWT Token,所以他就可以根據其中的 . 區分成三個部分,也就是 headerpayload 以及 signature

所以其實 JWT 格式,他就只是一段亂碼,只是我們可以使用 .,把內部的資訊區隔成三個部分而已。

而如果我們把下面這段 JWT 的亂碼,貼到 JWT 的官方網站 https://jwt.io/ 中的話:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoi5Y-k5Y-kIiwiaWF0IjoxNzIxMDAxNjAwfQ.G41XQGNNJ5Tp88U48aXh4n0XtGkpPkQ3xK6j43_61gE309hzyTVyciG5v05aVIvvY9NrApYiQdvwlMMrjRPFVV8xunghtKKFMj3kPx93Ll8Pf6n-tDiL_NZYqcusrgwtb-EDza80hMG5PTu75ogTIfRKr4jC0_FZzLaMix07LaZReoUSionTWTxJlm8qJc0BAFXgsaGNs9oVhCXOg_jJmOfFZBP0tD3q4xaKp9MTtLRTtslAhoAjPczdnPqaWGcaS8OY11RUTvvxijA7W-mPRlmqt0Hd_XForETUFZRdCKsPQIiGjkavycPtdiViVihQKstHlT4afEzYvzWSeK1cnw

就可以看到這個網站就會將此 JWT 分成三個部分,也就是剛剛提到的 header、payload、signature。

所以在了解 JWT 的運作原理之前,一定要先知道 「JWT 是由 header、payload 和 signature 這三個部分所組成」,每一個部分所負責的功能都不一樣,所以先了解 JWT 的結構是非常重要的!

而在 JWT 中,每一個部分所負責的功能都不一樣,以下分別介紹他們各自所負責的功能:

JWT 中的 header 部分:存放通用資訊 #

首先 header 的用途,就是用來存放一些通用的資訊,譬如說可以用來設定這個 JWT 的簽名算法、以及設定這個 JWT 的 Token 類型。

舉例來說,像是在下方的 header 例子中,裡面的 alg 就是用來設定這個 JWT 的簽名算法,而 typ 則是表示這個 Token 是 JWT 類型。

{
    "alg": "RS256",
    "typ": "JWT"
}

所以在 header 中,主要就是用來設定這個 JWT 的通用資訊。

補充:JWT 中的 Encode 和 Decode #

而大家如果觀察一下的話也可以發現,在 JWT 的官網中( https://jwt.io/ ),當我們在左側貼上 JWT 的亂碼之後,在右邊所呈現的會是 Decode(解碼)過後的結果。

像是以 header 的亂碼 eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9 為例,將他 Decode 之後,就可以得到原始的 JSON 字串 {"alg":"RS256","typ":"JWT"}

所以在 JWT 中,header 的亂碼看似好像有加密,但他實際上是完全沒有加密的!!!JWT 只是使用 Base64 將 JSON 字串給編碼一下而已,完全沒有加密的成分在裡面,因此所有人都有能力 Decode 這段亂碼,取得原始的 JSON 字串。

補充:不熟悉 Encode 和 Decode 的概念的話,可以回頭參考 密碼學中的 Encode、Encrypt、Hash 的差別在哪裡? 中的介紹。

JWT 中的 payload 部分:存放使用者的數據 #

了解了 header 的用途之後,接著我們可以來看一下 payload 的用途。

payload 的用途,就是用來存放使用者的數據,所以在 payload 中,我們就可以根據自己的需求,自由決定我們想要放什麼資訊在裡面。

所以像是在下面的 payload 例子中,裡面就存放了 "name": "古古" 的數據,用來表示這個使用者的名字為「古古」,因此我們就可以根據自己的需求,在 payload 中存放客製化的使用者數據了!

{
    "sub": "123",
    "name": "古古",
    "iat": 1721001600
}

補充 1:payload 中的常用變數 #

在客製化 payload 的數據時,我們也是可以使用 JWT 預先定義好的變數名稱來實作的。

舉例來說,sub 所代表的就是「使用者的 id 的值」,至於 iat 所代表的就是「這個 JWT Token 的創建時間」,這些都是 JWT 預設的變數名稱,算是使用 JWT 的一個默契。

所以大家在使用上,除了自己定義變數名稱之外,建議也可以多多利用 JWT 所定義的變數名稱,這樣就可以讓不同工程師所設計出來的 payload 長得差不多,就不用再每次都一個一個詢問「這個變數名稱的含義是什麼?」了。

除了 subiat 之外,這裡也補充常見的 JWT 變數名稱:

  • iss(issuer):此 JWT 的發行人
  • sub(subject):JWT 的使用者(通常是放使用者的 id 的值)
  • aud(audience):接收此 JWT 的收件人
  • exp(expiration time):此 JWT 過期失效的時間
  • iat(issued at time):此 JWT 是什麼時候被發布的(即是什麼時候被創建)
  • nbf(not before time):定義在某個時間以前,此 JWT 都是不可用的
  • jti(JWT ID):此 JWT 的唯一身份標誌,當 JWT 用來當作一次性的 Token 的時候,可以避免重放攻擊(即是這個 Token 只能使用一次)

但是老實說這些變數名稱都是用簡寫,真的很難記🥹,所以如果忘記了的話,就再回來查一下就好。

補充 2:不要在 payload 中存放敏感數據 #

在 payload 中,我們一樣是可以使用 Base64 去 Encode 或是 Decode,得到原始的字串或是編碼過後的亂碼。

像是在 JWT 的官網中,就會將左側的 paylod 的亂碼 eyJzdWIiOiIxMjMiLCJuYW1lIjoi5Y-k5Y-kIiwiaWF0IjoxNzIxMDAxNjAwfQ,Decode 成右邊的原始 JSON 字串 {"sub":"123","name":"古古","iat":1721001600}

也因為 payload 中的數據僅是使用 Base64 進行編碼而已,所以完全沒有安全性可言!!因此千萬不要將使用者的敏感數據(ex: 身分證字號)放在 JWT 中傳遞,因為 JWT 的 payload 是所有人都可以輕易解碼的。

所以通常在 payload 中,只會存放使用者的必要的資訊(ex: id 的值),後端到時再去根據這個 id 的值,去資料庫中查詢使用者的敏感數據。

JWT 中的 signature 部分:實作數位簽名 #

了解了 header 和 payload 的用途之後,最後則是要了解 signature 的部分。

signature 的用途,就是用來儲存「簽名」的計算結果,所以後端之所以可以無條件相信 JWT 中的 payload 數據,就是透過 signature 來達成的!

不過因為 signature 的實作機制比較複雜,因此在下一篇文章 JWT 是如何實作「數位簽名」的?揭秘 signature 的面紗 中,才有辦法完整介紹 signature 的精髓。

因此這裡大家只要先知道:後端之所以可以無條件相信 JWT 中的數據,全部都是 signature 的功勞就可以了!

JWT 總結 #

了解了上面的所有介紹之後,最後我們也可以來總結一下 JWT 中的內容。

JWT 的全稱為 JSON Web Token,通常是用來 「傳遞身份認證的數據」,並且 JWT 會由三個部分所組成,分別是:header、payload 以及 signature,每個部分之間使用 . 做分隔。

而在 header、payload、signature 這三個部分中,他們各自負責的功能如下:

  • header: 用來設定這個 JWT 的簽名算法、以及此 Token 的類型
  • payload: 用來儲存使用者的數據,可以根據自己的需求進行客製化
  • signature: 用來儲存「簽名」的計算結果

所以大家以後再看到 JWT 時,就可以用這個格式拆解 JWT,進而取得到其中的數據了!

補充:本文是擷取自我開設的線上課程 「資安一把罩!Spring Security 零基礎入門」 的內容,如果你想了解更多的資安內容、以及如何應用 Spring Security,歡迎參考課程簡介 (輸入折扣碼「HH202501KU」即可享 85 折優惠)。

結語 #

這篇文章我們介紹了 JWT 是由哪些部分所組成,以及每個部分所負責的功能為何,JWT 可以說是目前最流行的認證機制,所以搞懂 JWT 可以說是對工作上非常有幫助的!

如果你對後端技術有興趣的話,也歡迎免費訂閱 《古古的後端筆記》電子報 ,每週二為你送上一篇後端技術分享,那我們就下一篇文章見啦!

如果你對 JWT 的其他文章有興趣,也可以直接點擊下列連結跳轉到該文章(建議按照順序閱讀,才會有最佳的閱讀體驗):

  1. Session 和 JWT 的差別在哪裡?
  2. 密碼學中的 Encode、Encrypt、Hash 的差別在哪裡?
  3. JWT 是什麼?一次搞懂 JWT 的組成和運作原理 (本文)
  4. JWT 是如何實作「數位簽名」的?揭秘 signature 的面紗

免費訂閱《古古的後端筆記》電子報

每週二學習後端技術,和 2700 人一起變強💪