解碼後的 JWT 證明了什麼
JWT 解码器向您显示令牌声明的内容。它無法向您表明這些說法是否屬實。本指南介紹了這三個部分是什麼、解碼做什麼和不做什麼,以及存在於兩者之間的攻擊。
三個段,其中兩個只是 JSON
JWT 的常見形式是 JWS:由點分隔的三個 base64url 區段。第一個是標頭,第二個是有效負載,第三個是簽名。
標頭和負載是經過 base64url 編碼的普通 JSON 物件。已編碼,未加密。任何持有令牌的人都可以立即讀取兩者,無需密鑰——這不是缺陷,而是設計。 JWT 是一份簽署的聲明,而不是密封的信封。簽名保證該聲明未被更改;它沒有任何作用來保持其私密性。
結果值得明確說明,因為它經常被忽略:永遠不要在 JWT 有效負載中放入任何機密內容。不是密碼,不是完整的國家標識符,也不是內部系統詳細資料。假設有效負載是公開的,因為對於擁有令牌的任何人來說,它都是公開的。
第三段是簽名,根據前兩段計算。它是唯一具有任何安全價值的部分,並且是解碼器無法評估的部分。
解碼證明什麼:什麼都沒有
這是整個指南的重點。解碼 JWT 會將兩個 base64url 字串解析為 JSON。它確認令牌的格式良好。它不確認該令牌是真實的,它是由 "iss" 聲明中指定的一方頒發的,該聲明未經編輯,或者它曾經有效。
任何人都可以建立代幣。取得任何 JWT,將“角色”:“用戶”更改為“角色”:“管理員”,重新編碼有效負載,在末尾釘上任何簽名,解碼器將像顯示原始內容一樣自信地顯示您編輯的宣告。它無法知道差異,因為檢查差異是一個不同的操作,需要解碼器沒有的金鑰。
因此,當解碼器(這個解碼器或任何其他解碼器)向您顯示「exp: 2026-01-01」時,它真正告訴您的是:此令牌包含一個在該日期到期的聲明。该声明是否有意义完全取决于签名是否有效,而签名尚未经过检查。
該工具僅進行解碼,並且每次都會在頁面結果旁邊註明。不在腳註中。原因是對此保持沉默的解碼器正在訓練其用戶讀取未經驗證的數據,就像它已被驗證一樣,而這種習慣是整個身份驗證錯誤家族的根源。
為什麼這個工具不提供驗證
驗證需要網頁不能負責任地擁有的三樣東西:發行者的金鑰、預先固定的演算法以及關於拒絕什麼的策略。
關鍵是顯而易見的問題。對於 HMAC 演算法(HS256 和類似演算法),金鑰是一個共享秘密——與創建令牌相同的秘密。將其貼到網頁中意味著將可以產生有效令牌的憑證貼到網頁中。對於 RSA 和 ECDSA,公鑰不是秘密的,但您仍然需要從正確的 JWKS 端點取得正確的公鑰並信任您所擁有的。
該演算法是一個微妙的問題,也是兩次著名攻擊的根源。第一個是 alg: "none":標頭聲明令牌是未簽署的,並且尊重標頭而不是其自己的配置的驗證程序接受任何內容。第二個是 RS256 到 HS256 的混淆:攻擊者獲取公鑰(根據定義,即公共密鑰)將標頭更改為 HS256,並使用該公鑰作為 HMAC 密鑰對令牌進行簽署。從令牌中讀取演算法並尋找“密鑰”的驗證者將對其進行驗證。
這兩種攻擊都源自於同一個錯誤:讓令牌告訴驗證者如何檢查令牌。正確的驗證程序會忽略標頭的演算法並使用其配置的演算法。這是屬於信任令牌的系統的決定,而不是便利工具的決定,也不是將某些內容貼到表單中的人的決定。
為什麼不將生產令牌貼到任何地方
存取令牌是不記名憑證。這就是授權標頭中 "bearer" 的意思:誰擁有它,誰就是您。沒有第二個因素,通常也沒有辦法區分被盜令牌和合法令牌。在過期之前,它是您帳戶的工作金鑰。
因此,將即時令牌貼到任何網頁中就是向該頁面傳遞憑證。這個在本地解碼所有內容,並且在頁面加載後不發出網絡請求 - 您可以在瀏覽器的網絡面板中確認這一點,而且您應該這樣做,因為這需要十秒鐘。但請注意這個論點實際上是什麼:在網站上聲稱該網站是值得信賴的。每個竊取代幣的網站都提出完全相同的主張,訪客一眼就無法看出差異。
安全習慣並不取決於正確判斷地點。使用過期的令牌、測試環境令牌或您為此目的鑄造的令牌。如果您已經將生產令牌貼到某處(任何地方),請旋轉它。撤銷的成本很低;事件不是。
這同樣適用於簽署金鑰。沒有正當理由在網頁中輸入 HMAC 秘密或私鑰,任何要求「驗證」您的代幣的網站都要求具有偽造令牌的能力。這就是該工具沒有驗證功能的具體原因:該功能需要請求。
閱讀重要的聲明
RFC 7519 註冊一小組宣告名稱。 「iss」是發行者,「sub」是代幣的主題,「aud」是目標受眾,「exp」是到期時間,「nbf」是最早有效時間,「iat」是發行時間,「jti」是用於重播檢測的唯一ID。其他一切都是特定於應用程式的。
時間聲明是 NumericDate 值:自 Unix 紀元以來的秒數,而不是毫秒。這常常讓人感到困惑,因為大多數 JavaScript 時間值都是毫秒。似乎在 1970 內到期的令牌通常會被賦予一個毫秒值;看起來在 55000 年到期的一個通常在某個地方有第二個值乘以 1000 。
當您調試時,“aud”值得特別注意。完全有效的令牌仍然可能是錯誤的令牌,因為它是為不同的受眾發行的。檢查簽名但不檢查受眾的驗證者將接受完全為另一個服務鑄造的令牌——這是共享身分提供者的系統中真正的特權升級路徑。
該工具以 UTC 格式呈現時間聲明,將過期令牌標記為已過期,並將其與提醒配對,即過期聲明僅在簽章有效時才有意義。之所以有提醒,是因為「它說它尚未過期」正是未經驗證的數據習慣造成損害的時刻。
進行信任的系統的簡短清單
如果您正在編寫接受令牌而不僅僅是檢查令牌的程式碼,則以下是正確驗證程式所做操作的簡短版本。
- 在閱讀任何聲明之前,請先使用您從帶外獲得的金鑰驗證簽名。
- 將演算法固定在您自己的配置中。切勿从令牌标头中读取它。無條件拒絕 "none"。
- 根據可信時脈檢查 "exp" 和 "nbf",最多允許較小的偏差。
- 根據您期望的值檢查 "iss" 和 "aud"。令牌上的有效簽名對於其他人來說仍然是錯誤的令牌。
- 使用適合您的平台的經過審查的庫,而不是自己組裝。此列表中的每一項都在其中,因為實作中出現了錯誤。
- 保持令牌生命週期較短,並具有撤銷路徑。短暫的令牌可以限制您尚未註意到的洩漏造成的損害。
你貼的內容會發生什麼
- 每個轉換、哈希、解碼和差異都在您的瀏覽器標籤中運行。不會在伺服器上傳、記錄或儲存任何輸入,因為頁面載入後就不再涉及伺服器。
- 雜湊值來自瀏覽器自己的 Web Crypto 實現,UUID 來自其加密安全隨機產生器。兩者都不涉及網絡調用。
- 您鍵入的任何內容都不會寫入本機儲存或 cookie。重新載入頁面會丟棄它;關閉選項卡將丟棄它。
- 站點範圍的分析僅在配置的規範生產主機上運行,並在隱私權政策中披露;本地和預覽主機拒絕它。貼上的值、令牌、URL 和文件內容不包括在 ToolAcre 自己的分析事件中。目前配置中停用廣告。
- 也就是說:JWT 或 API 金鑰是即時憑證。安全的習慣是永遠不要將其粘貼到不是您編寫的網頁中,無論其聲明多麼可信 - 包括這個。
問題
這個工具可以驗證簽章嗎?
不,而且永遠不會。它會對標頭和有效負載進行解碼並顯示它們包含的內容。它不檢查簽名,因此它顯示的任何內容都無法證明令牌是真實的、未更改的或由其指定的任何人頒發的。
那我怎麼知道令牌是真的呢?
透過使用發行者的金鑰驗證簽名,使用經過審查的庫,並將演算法固定在您自己的配置中,而不是從令牌中讀取。這是在合法持有密鑰的環境中信任令牌的服務的工作。
當我在這裡解碼時,我的令牌會發送到任何地方嗎?
不會。解碼使用頁面自己的 JavaScript 在瀏覽器標籤中進行,並且頁面載入後不會發出網頁請求。您可以在瀏覽器的網頁面板中驗證這一點。您仍然不應該將生產令牌貼到網路工具中作為一種習慣,因為這種習慣必須在不誠實的網站上起作用。
為什麼任何人都可以讀取我的 JWT 有效負載?
因為有效負載是 base64url 編碼的,而不是加密的。 JWS 是一份簽署的聲明,而不是密封的聲明。如果您需要使內容不可讀,則需要 JWE(加密令牌格式),然後解碼器在沒有金鑰的情況下根本無法向您顯示任何內容。
什麼是 alg:"none"?
聲明令牌未簽署的標頭值。它存在於透過其他方式保證完整性的上下文規範中,並且它是一個長期陷阱:信任標頭演算法的驗證者將接受任何聲明 "none" 的令牌。該工具每當它出現時都會對其進行標記。
我的令牌有五個段,無法解碼。為什麼?
五個段落意味著一個 JWE(一種加密令牌),而不是一個簽署的 JWS。如果沒有解密金鑰就無法讀取其內容,因此解碼器實際上無法顯示任何內容。該工具明確識別該情況,而不是報告模糊的解析失敗。
到期時間看起來有 1000 的錯誤。
JWT 時間聲明是 NumericDate:自紀元以來的秒數,而不是毫秒。 Date.now() 產生的值太大了一千倍。此工具包中的時間戳實用程式在兩者之間進行轉換,並始終告訴您它使用的單位。
將 JWT 儲存在 localStorage 中安全嗎?
這是一種權衡,而不是是或否。 localStorage 可由在您的來源上執行的任何 JavaScript 讀取,因此單一 XSS 漏洞就會洩漏令牌。 httpOnly cookie 無法被 JavaScript 讀取,但需要 CSRF 保護。誠實的總結是,兩者都不是免費的,決定取決於應用程式的威脅模型。
限制
- 該工具僅解碼。它不驗證簽名,這是一個永久性的設計決策,而不是一個缺少的功能——請參閱上面的指南以了解原因。
- 如果沒有金鑰,加密令牌(JWE,五個段落)根本無法解碼。該工具識別出它們並停止。
- 巢狀 JWT(有效負載本身就是令牌的令牌)不會自動解包。解碼內部令牌作為一個單獨的步驟。
- RFC 7519 中定義的註冊集之外的聲明含義是特定於應用程式的,因此該工具會顯示它們的值而不解釋它們。
- 此處顯示的到期時間僅反映令牌對其自身的聲明。該聲明是否有意義取決於該工具不檢查的簽名。
- 大於 200,000 個字元的令牌將被拒絕。任何真正的 JWT 都要小幾個數量級。