要解碼一個精簡 (compact) 的 JWT,請以 '.' 字元分割字串,使用 java.util.Base64 對前兩個段落進行 Base64url 解碼,並將每個段落解析為 UTF-8 JSON。第三個段落是簽章,在沒有金鑰的情況下無法安全檢視,因此僅憑解碼並無法證明權杖是真實的。若想在不將 jjwt、java-jwt 或 Nimbus JOSE+JWT 加入專案的情況下進行一次性檢查,JWT 解碼器會在您的瀏覽器中本機執行相同的分割與解碼作業。Java 開發人員常在 OAuth 回呼除錯、測試固定資料審查,或跨服務健全性檢查時將權杖貼進去。此工具會呈現標頭 (header)、承載資料 (payload),以及它所辨識的 RFC 7519 註冊聲明 (registered claims),因此您可以在把權杖接入 Spring Security 篩選器或自訂驗證篩選器之前,先確認權杖所聲明的內容。解碼回答的是「這個權杖說了什麼」;驗證回答的是「我是否應該相信它所說的」。把這條界線劃清楚,才能讓一個有用的除錯輔助工具,變成一條安全的工作流程。

how to decode jwt token in java
如何在 Java 中解碼 JWT 權杖:本機檢視聲明

精簡 JWT 的結構:標頭、承載資料、簽章

RFC 7519 將精簡 JSON Web Token 描述為三個以單點連接的 Base64url 編碼段落:header.payload.signature。每個段落使用 RFC 4648 中定義的 URL 安全字母集:26 個大寫字母、26 個小寫字母、數字 0 到 9、連字號,以及底線。填充字元刻意省略,因為段落長度是由編碼後的位元組數固定下來的,所以帶填充的權杖在結構上就是無效的,嚴格的解碼器會將其拒絕,而不是悄悄接受另一種格式。

標頭帶有關於權杖的中繼資料:簽章或加密演算法 (alg 欄位)、選擇性的媒體類型 (通常為 typ: JWT),以及簽發者選擇加入的任何其他參數。承載資料帶有聲明,包括來自 RFC 7519 的註冊名稱、在別處註冊的公開名稱,以及您應用程式定義的私有名稱。第三個段落是簽章,若為未受保護的權杖則為空字串。僅解碼的工具只會檢查第三個段落是否符合精簡 Base64url 的形狀;其位元組永遠不會被解讀為已驗證的簽章。

Java 的 java.util.Base64 類別透過 Base64.getUrlDecoder() 公開一個 URL 安全的解碼器。由於精簡 JWT 會去掉結尾的 = 字元,您通常會將它與一個小型填充輔助函式搭配使用,或是在段落長度整齊的情況下呼叫 Base64.getMimeDecoder()。解碼後,這些位元組應被解讀為 UTF-8 JSON。這就是完整的解碼管線;圍繞在它之外的一切都屬於驗證。

Java 開發人員解碼 JWT 的兩種方式

大多數 Java 專案傾向使用第三方函式庫,而不是自己手寫解碼。常見的三個選擇是:

  • jjwt (io.jsonwebtoken):串接式 (fluent) 的建構 API,對 Spring 友善,支援 JWS 與 JWE。
  • java-jwt (com.auth0):介面小而精實,適合用於權杖簽發與解析。
  • Nimbus JOSE+JWT:Spring Security OAuth 所使用的參考級品質函式庫。

每個函式庫都公開 parseSignedClaims(...) 或 decode(...) 等輔助方法,在內部進行分割、Base64url 解碼、解析 JSON,並在提供金鑰時驗證簽章。解碼步驟是廉價且無副作用的部分;昂貴且涉及安全性的是驗證,它需要金鑰與政策。

若只是為了偶爾檢查、除錯 OAuth 回呼、讀取測試固定資料,或比較兩個服務看到的內容,特地拉入一個相依套件就太殺雞用牛刀了。這正是本機瀏覽器解碼器填補的空缺:它能在不更動您的建置、不開啟 IDE、或將權杖送往遠端服務的情況下,顯示精簡權杖的標頭與承載資料。

在瀏覽器中本機解碼 JWT 權杖

JWT 解碼器是一個刻意設計得很精簡的工具,在您的瀏覽器分頁中執行與 java.util.Base64 相同的分割與 Base64url 處理作業。請依照下列步驟操作:

  1. 複製一份標準 header.payload.signature 格式的精簡權杖。請確認沒有夾帶多餘的空白、換行,或前後引號。
  2. 將其貼到 JWT 解碼器頁面上的輸入欄位中。
  3. 選擇 Decode JWT。頁面會以兩個點分割字串,驗證每個段落是否為未填充的 Base64url,將標頭與承載資料解碼為 UTF-8,並將其解析為 JSON。
  4. 閱讀所呈現的標頭物件、承載資料物件,以及頁面所辨識的任何 RFC 7519 註冊聲明。
  5. 將結果視為「未經驗證」的資訊。頁面會將每一次成功的解碼標示為未經驗證,以免一個方便的檢查步驟被誤認為是安全性檢查。
  6. 結束後,請清除輸入欄位與剪貼簿。權杖可能帶有您不希望殘留的個人識別資訊、租戶資料或範圍 (scope)。

若想採用更廣泛、完全不寫程式碼的瀏覽器工作流程,請參閱 在瀏覽器中無需撰寫程式碼即可解碼 JWT 權杖。

解碼後的標頭與承載資料包含什麼

標頭幾乎總是一個只有兩個常見欄位的小型 JSON 物件:alg (簽發者使用的演算法,例如 HS256、RS256 或 ES256) 與 typ (通常為 JWT)。承載資料則承載應用程式邏輯,它可以在同一個扁平物件中混合註冊聲明、公開聲明與私有聲明。

下表摘要列出 RFC 7519 所定義的註冊聲明。解碼器會在這些聲明存在時顯示,但它不會強制執行任何一項。

Claim完整名稱意義
issIssuer簽發該 JWT 的主體。
subSubject該 JWT 所描述的主體。
audAudienceJWT 預期的接收者。
expExpiration TimeJWT 不得再被接受的時間點。
nbfNot BeforeJWT 不得在此時間之前被接受。
iatIssued AtJWT 簽發的時間。
jtiJWT ID可用來防止重放 (replay) 的唯一識別碼。

針對 exp、nbf 與 iat,工具會同時顯示原始的 NumericDate 數值與 ISO 時間戳記。NumericDate 是以 Unix 秒數表示的慣例,並非該權杖目前可被接受的保證,因為時鐘偏移、接收者,以及簽發者的政策都會影響。對於 aud 聲明,它可能是單一字串或陣列;解碼器會原樣呈現 JSON 值,而不會判定它是否符合您的應用程式。自訂聲明會保留顯示在原始承載資料中,因為 JWT 允許私有聲明名稱,但頁面不會賦予它們任何特殊意義。

瀏覽器解碼器不會做的事

這個頁面是一個「僅供解碼」的工具。它不接受秘密金鑰或公開金鑰、不驗證 JWS 簽章、不檢查簽發者、不檢查接收者、不套用時鐘偏移、不解密 JWE,也不做出授權決策。它不會上傳權杖、不會將權杖送往 API、不會擷取簽章金鑰、不會儲存副本,也不會建立帳號。解碼完全在瀏覽器中進行。

一份可讀的承載資料仍然可能是偽造、過期、針對不同接收者,或使用您不信任的金鑰所簽署的。若您需要驗證權杖,請在負責安全性決策的服務中使用一套有維護的 JWT 函式庫,並於該處驗證演算法、金鑰、簽發者、接收者、效期,以及任何應用程式特定的要求。解碼器無法顯示加密 JWE 中的內容、無法修復毀損的權杖、無法找出簽章金鑰,也無法告訴您簽章是否正確。

Java 在信任權杖之前仍必須驗證的事項

在任何 JWT 函式庫中,解碼與驗證是兩種不同的操作。成功解碼之後,Java 端仍需確認:

  • 標頭中的 alg 是應用程式所接受的演算法。拒絕 none,以及拒絕演算法混淆 (例如將 RS256 權杖拿 HMAC 金鑰驗證),是不可妥協的底線。
  • 簽章與標頭和承載資料相符,使用的是預期的金鑰。該金鑰本身必須來自信任的金鑰存放區或 JWKS 端點,而不是從權杖中取得。
  • iss 聲明與預期的簽發者識別碼相符。
  • 當 aud 為必要時,aud 聲明包含您應用程式的識別碼。
  • 目前時間晚於 nbf 且早於 exp,並允許您安全政策所允許的時鐘偏移。
  • 若您的服務有追蹤重放,任何 jti 值在近期內未被使用過。

這些檢查位於您的驗證篩選器、資源伺服器組態,或負責信任決策的 Spring Security OAuth2ResourceServer 設定之中。瀏覽器解碼器是讀取權杖所「聲明」之內容的側通道;Java 的驗證路徑才是決定權杖是否可被接受的那一條。

Java 開發人員檢查權杖時的安全工作流程

即使 JWT 並非密碼,它們經常帶有個人識別資訊、租戶資料、範圍,以及其他應用程式特定的數值。請以您對待 session cookie 或 API 金鑰的同等謹慎來對待它們:

  • 只在您有權檢查權杖的環境中取得權杖。測試固定資料與本機模擬 (mock) 沒問題;不小心擷取到的正式環境 bearer 權杖則不行。
  • 將權杖貼到本機頁面,而不是貼到公開的線上解碼器。JWT 解碼器在您的瀏覽器中執行,絕不會將權杖傳送出去。
  • 檢視 alg 欄位與註冊聲明,完成後清除輸入欄位與剪貼簿。
  • 避免將正式環境的憑證貼到共用螢幕、問題追蹤系統、聊天訊息、螢幕擷圖,或第三方線上解碼器中。
  • 若您需要獨立轉換 Unix 時間戳記,Unix 時間戳記轉換器可在不上傳數值的情況下,以 UTC、本地時間與 ISO 8601 格式呈現 NumericDate。

解碼步驟是例行的開發工作。讓解碼路徑維持在本機,並把驗證路徑留在 Java 服務內,才能將一個有用的除錯工具,轉化為可永續經營的安全性 posture。

延伸閱讀:線上產生 JWT 權杖:HS256 vs RS256。