JWT 身分驗證的運作方式——不用工作階段的權杖

JWT 身分驗證的運作方式,畫在一張互動畫布上:憑據、由三段組成的已簽章權杖,以及每一個請求如何以無狀態的方式獲得驗證。

JSON Web Token 是一份經過簽章、自我完備的身分陳述:伺服器在登入時製作它一次,之後每一個請求都用這個權杖自證,而不需要再去查工作階段。

JWT 身分驗證的運作方式——不用工作階段的權杖

The interactive FlowJam canvas for this explanation — every lane, row and arrow above is a real QueryChart diagram you can open and edit.

How to read this visual

  • 由左至右讀:登入、簽發權杖、已驗證身分的請求。
  • 用戶那一列與伺服器那一列交替出現,所以每一個箭頭不是用戶提供了甚麼,就是伺服器決定了甚麼。
  • 登入直欄與請求直欄頂部那兩個拒絕形狀,是失敗的終點——畫布上每一個決策都會通向其中一個。

證明你是誰

「用戶提交電郵與密碼」與「伺服器對照資料庫驗證憑據」是整條流程裡唯一有密碼存在的地方。「憑據是否有效?」分成順利的路徑與「登入被拒絕」。這一段是傳統的身分驗證——屬於 JWT 的那一部分,要等憑據檢查通過之後才開始。

製作權杖

「伺服器組出標頭、內容區與簽章」是這張圖解的核心。標頭指明簽章的演算法;內容區載著那些聲明——用戶 id、有效期,以及任何授權範圍;簽章把它們綁在一起,令權杖無法在不被察覺的情況下被改動。「伺服器用自己的密鑰為權杖簽章」就是令它值得信任的那個動作:只有持有密鑰的伺服器才產生得出有效的簽章。「用戶端收到 JWT 並儲存起來」把這件產物交到用戶端手上,它會一直留在那裡,直至到期。

無狀態的驗證

「用戶端在 Authorization 標頭裡送出 JWT」是流程中不斷重複的那部分的開端,而「伺服器用自己的密鑰驗證簽章」正是這套做法可以擴展的原因:重新核算一次簽章是一次運算,不是一次資料庫查詢,所以並沒有一個中央的工作階段儲存需要查閱。「簽章有效而且未到期?」加上了時間的檢查,把無效或已到期的權杖送去「請求被拒絕並回傳 401」,把有效的送去「伺服器信任這些聲明並處理該請求」。

Key relationships and takeaways

  • 一個 JWT 由三部分組成——標頭、內容區、簽章——以句點連接;內容區可以讀取,但一經改動即可察覺。
  • 簽章把身分變成一種能力:持有一個有效而且未到期的權杖,本身就是這個請求的身分驗證。
  • 驗證是無狀態的——重新核算簽章取代了查詢工作階段。
  • 權杖必須由用戶端安全地儲存,並隨每一個請求送出,所以它的有效期才是真正的安全邊界。
  • JWT 與 OAuth 是互相配合的:OAuth 決定用戶端可以做甚麼,而 JWT 是承載這個決定的權杖其中一種常見格式。

When to use this visual

  • 向一支新的後端團隊講解為甚麼不需要工作階段表,以及簽章實際上證明了甚麼。
  • 為一個橫向擴展令共用狀態變得棘手的服務,在 JWT 與伺服器端工作階段之間做選擇。
  • 在微服務裡信任一個權杖之前,先覆核它的聲明——有效期、簽發者、受眾。

運作方式

  1. 列出你的權杖實際載有的聲明

    在「伺服器組出標頭、內容區與簽章」那一步,加上你實際簽發的聲明——sub、exp、iss、aud,以及任何授權範圍——讓這張圖記錄下你的權杖合約。

  2. 加上更新權杖的流程

    在到期之後插入更新權杖的路徑:用戶端出示一個長效的更新權杖,伺服器簽發一個新的存取權杖,工作階段不需要重新登入就繼續下去。

  3. 寫明你的簽章密鑰策略

    在簽章那一步標註你的密鑰管理方式——單一共用密鑰(HS256),還是一組公開密鑰與私人密鑰(RS256)——因為這個選擇決定了誰可以驗證這個權杖。

  4. 加上失敗的分支

    把已到期、格式錯誤與被竄改的權杖都列為明確的終點,令這張圖涵蓋你的 API 實際會回傳的那些拒絕。

常見問題

甚麼是 JWT?它裡面有甚麼?

JSON Web Token 是一串以句點分隔成三段的字串:一段標頭,說明簽章演算法;一段內容區,載有關於用戶以及權杖存活時間的聲明;以及一段簽章。標頭與內容區是經過 base64 編碼的 JSON——任何人都讀得到——而簽章就是令它們無法在沒有簽章密鑰的情況下被改動的東西。

為甚麼 JWT 身分驗證叫做無狀態?

因為伺服器對這個工作階段甚麼都不儲存。每一個請求都帶著權杖到達,伺服器就地驗證簽章與有效期。沒有工作階段表需要查詢,也沒有狀態需要在多台伺服器之間複製,而這正是這套做法可以橫向擴展的原因。代價是:如果沒有額外的機制,一個權杖在到期之前無法被撤銷。

如果任何人都讀得到內容區,JWT 還安全嗎?

讀得到與可以信任是兩回事。內容區並沒有加密——不要把秘密放進去——但簽章意味著任何改動都會令權杖失效,所以用戶端無法更改自己的聲明。傳輸的安全性靠權杖在 HTTPS 之內傳送,而它所開啟的資料,則由資源伺服器執行那些聲明來保護。

JWT 與 OAuth 有甚麼關係?

它們解決的是問題的不同一半。OAuth 是授權協議——用戶端如何取得權限與權杖。JWT 則是一種權杖格式。實務上 OAuth 的存取權杖往往就是 JWT:授權伺服器簽發一個載有授權範圍的 JWT,而資源伺服器負責驗證它。這張畫布講的是身分驗證那一半;OAuth 那張圖解講的是委託那一半。

用 QueryChart(FlowJam)編輯這張圖解

把上面這張 JWT 畫布開啟為你自己的圖表——把用戶端與伺服器改名為你自己的服務,並註明你自己的聲明。

用 QueryChart(FlowJam)編輯這張圖解

互動圖解的更多內容