開發者工具 / 037
JWT 解碼器
解碼 JWT 的 header 與 payload,將常見時間 claim 轉成可讀日期並提示是否過期;不驗證簽章。
不要貼正式環境的 token。 JWT 是憑證,拿到的人可以直接冒用你的身分直到它過期。解碼在你的瀏覽器裡完成、 不會送到任何地方,但你沒辦法從外觀判斷一個網頁工具實際做了什麼——這個懷疑對任何線上 JWT 工具都適用,包括這一個。要檢查正式 token 請用本機的 CLI。
貼上 JWT 後會立即解碼。也可以先按「帶入示範 token」看輸出長什麼樣。
為什麼做這個
除錯 JWT 時,常見需求是查看內容與確認時間欄位。這個工具只做本機解碼與時間顯示,不要求輸入簽章密鑰,也不把「能解碼」當成 token 已通過驗證。
這個工具怎麼用
貼上 JWT 就會立即解碼。最上面顯示的是最常被查的資訊:過期了沒、還有多久到期、用什麼演算法簽的。下面逐項列出 payload 的每個 claim,並附上標準 claim 的中文說明。
時間類的 claim 是 Unix 秒數,不是毫秒。 `exp`(到期)、`iat`(簽發)、`nbf`(生效)都是從 1970 年起算的秒數,這是 JWT 規格與 JavaScript `Date` 最容易出錯的落差——`new Date(payload.exp)` 會得到 1970 年的某一天,要乘 1000 才對。工具已經幫你換算成可讀時間。
這個工具不驗證簽章,這是刻意的。 驗簽需要密鑰,而把正式環境的密鑰貼進任何網頁工具都是不該做的事。能解碼不代表 token 有效——任何人都能自己編一個內容合理但簽章是亂打的 JWT。真正的驗證必須在後端用對應的函式庫做。
如果 header 的 `alg` 是 `none`,工具會另外警告。那代表這個 token 完全沒有簽章保護,任何人都能修改內容。正式環境的驗證邏輯應該明確拒絕 `none`,這是曾經造成大量漏洞的經典陷阱。
JWT 由三段組成,用點號分隔:`header.payload.signature`。前兩段是 Base64URL 編碼的 JSON,任何人都能解開;第三段是簽章,只有持有密鑰的一方才能產生或驗證。常見的 payload 欄位(claim)依 RFC 7519 定義:`iss` 簽發者、`sub` 主體(通常是使用者 ID)、`aud` 目標對象、`exp` 到期時間、`nbf` 生效時間、`iat` 簽發時間、`jti` 唯一識別碼。自訂的欄位則由各系統自行決定,例如角色或權限。
除錯時建議照這個順序看:先看 `exp` 是否已過期,再看 `aud` 與 `iss` 是不是你的服務預期的值,最後看自訂欄位(角色、租戶)是否正確。很多「登入後沒有權限」的問題,其實是 token 簽發時帶的欄位與後端檢查的欄位對不上,用解碼工具比對一次就能找出差異。
常見問題
為什麼不驗證簽章?
因為驗簽需要密鑰。把正式環境的簽章密鑰貼進網頁工具,等於把整個系統的認證能力交出去——拿到密鑰的人可以自己簽發任何 token。這個工具刻意不提供這個功能,需要驗簽請在後端或本機的 CLI 做。
我的 token 貼進來安全嗎?
解碼全程在你的瀏覽器裡完成,不會送到任何地方。但你無法從外觀判斷一個網頁工具實際做了什麼——這個懷疑對所有線上 JWT 工具都適用,包括這一個。所以頁面上明確建議不要貼正式環境的 token,要檢查正式 token 請用本機工具。
JWT 裡的內容是加密的嗎?
不是。JWT 的 header 與 payload 只是 Base64URL 編碼,任何人拿到 token 都能直接讀出裡面所有內容。簽章保護的是「內容沒有被篡改」,不是「內容看不到」。所以絕對不要把密碼、身分證號這類敏感資料放進 payload。
exp 顯示的時間跟我預期的差很多?
檢查你的系統是不是把 exp 當成毫秒了。JWT 規格規定時間 claim 是 Unix 秒數,但 JavaScript 的 Date 用毫秒,差 1000 倍。另一個可能是時區——工具顯示的是你裝置本地時區的時間,而 exp 本身是絕對時間點。
alg 是 none 代表什麼?
代表這個 token 沒有簽章,內容可以被任意修改。歷史上有不少漏洞是後端接受了 alg: none 的 token 而被繞過認證。正式環境的驗證邏輯應該明確指定允許的演算法清單,不要相信 token 自己宣告的 alg。
token 還沒到 exp,為什麼伺服器說過期?
常見原因有三個:伺服器與簽發端的時鐘有誤差、`nbf`(生效時間)還沒到、或是伺服器對該 token 另外做了撤銷(登出後列入黑名單)。解碼只能告訴你 token 本身寫了什麼,伺服器是否接受還取決於它的驗證邏輯。