JWT 解析器指南:如何安全地解碼、驗證與檢視 JSON Web Token
你的生產環境驗證突然掛了。使用者一直收到「Invalid Token」錯誤,你得趕快查出原因。你打開 JWT,卻發現它像一串亂碼:三個用點分隔的隨機字元區塊。資料就藏在裡面,但沒有解析器你根本讀不出來。
JWT 解析器(JWT Parser) 是一種專門工具,依照 RFC 7519 標準拆解 JSON Web Token 的三個部分——Header、Payload 與 Signature。截至 2026 年 4 月,這類解析器會解碼 Base64URL 編碼的資料,並用密鑰或公鑰驗證簽章,確保 token 未被竄改,藉此擋下「alg: none」攻擊之類的威脅。
JWT 解析器實際在做什麼
把 JWT 解析器想像成一個翻譯員。它把一長串不透明的字串還原成可讀的 JSON 物件。這對現代應用程式中管理使用者身分與保障資料交換安全來說,是最基礎的能力。
在內部,解析器會找出將 token 切成三段的那兩個句點(.):
| 區段 | 用途 | 是否編碼 | 無金鑰是否可讀 |
|---|---|---|---|
| Header | 中繼資料:簽章演算法(HS256、RS256) | Base64URL | 是 |
| Payload | 聲明:使用者資料、到期時間、角色 | Base64URL | 是 |
| Signature | 證明來源真實性的數位封印 | HMAC/RSA | 否——需要金鑰 |

逐步解碼:內部發生了什麼
讓我們追蹤一個真實的 token。看看下面這個 JWT 範例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4iLCJpYXQiOjE3MDAwMDAwMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
步驟 1:以句點切割
[0] eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
[1] eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4iLCJpYXQiOjE3MDAwMDAwMDB9
[2] SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
步驟 2:Base64URL 解碼區段 [0](Header)
{
"alg": "HS256",
"typ": "JWT"
}
步驟 3:Base64URL 解碼區段 [1](Payload)
{
"sub": "1234567890",
"name": "John",
"iat": 1700000000
}
步驟 4:驗證區段 [2](Signature)——需要密鑰
解析器把 Base64URL 編碼後的 header 加上「.」再接上 payload,接著用密鑰計算 HMAC-SHA256。若結果與區段 [2] 相符,這個 token 就是真實的。
重要安全提醒:Base64URL 不是加密
新手開發者常見的陷阱,是以為編碼後的 header 與 payload 有被加密。並沒有。正如 JustUse.me 所指出,Base64URL 編碼只是讓 JSON 能安全地透過 URL 與標頭傳輸。任何拿到 token 的人,都可以在沒有密碼或金鑰的情況下解碼出 payload。
絕對不要把敏感資料(密碼、身分證字號、API 金鑰)放進 JWT payload。 只要攔截到 token,這些資料就完全曝光。
簽章驗證:安全閘門
雖然任何人都能讀取 token 的資料,但真正保障系統安全的是簽章驗證。JWT 解析器不只讀取資訊——它還能證明資訊的來源。
解析器會用 header、payload 與一把金鑰重新計算簽章,再檢查結果是否與 token 上的簽章相符。若不相符,代表 token 已被竄改。
兩大演算法家族
| 演算法 | 金鑰類型 | 運作方式 | 常見使用情境 |
|---|---|---|---|
| HS256(HMAC) | 對稱——簽署與驗證使用同一把密鑰 | 雙方共享同一個密鑰 | 單一服務驗證、同一團隊內的微服務 |
| RS256(RSA) | 非對稱——私鑰簽署、公鑰驗證 | 傳送方保留私鑰;任何持有公鑰者皆可驗證 | OAuth2 提供者、第三方 API 整合 |
| ES256(ECDSA) | 非對稱——與 RSA 模式相同但採橢圓曲線 | 金鑰更小、驗證更快 | 行動應用、對效能敏感的服務 |

「alg: none」攻擊
這是最危險的 JWT 漏洞之一。攻擊者竄改 header,宣稱 "alg": "none" 並移除簽章。實作不良的解析器可能會接受這種 token,在毫無驗證的情況下把它當成有效 token。
防禦方式: 你的解析器必須明確拒絕任何演算法為「none」、或不符合你預期演算法的 token。開發 Apify JWT 工具的 Stas Persiianenko 強調,雖然 token 設計上就是透明的,但其安全性取決於解析器是否嚴格拒絕未簽署或遭竄改的 token。
decoded = jwt.decode(token, key, algorithms=None) # 絕對不要這樣寫
decoded = jwt.decode(token, key, algorithms=["HS256"])
標準 JWT 聲明:每個欄位的意義
JWT 解析器會從 payload 中擷取「聲明(claims)」。這些聲明遵循 JOSE(JSON Object Signing and Encryption) 框架,以確保跨系統相容性。
| 聲明 | 完整名稱 | 用途 | 範例值 |
|---|---|---|---|
iss |
Issuer | 誰簽發了這個 token | "auth.example.com" |
sub |
Subject | token 所代表的使用者或實體 | "user:12345" |
aud |
Audience | token 的預期接收者 | "api.example.com" |
exp |
Expiration Time | token 何時失效 | 1700000000(Unix 時間戳) |
iat |
Issued At | token 建立時間 | 1699999999 |
nbf |
Not Before | token 在此時間之前無效 | 1699999999 |
jti |
JWT ID | token 的唯一識別碼 | "a1b2c3d4" |
使用非對稱簽章時,解析器常會參照 JWK(JSON Web Key)——一種用 JSON 表示公鑰的結構。解析器會自動從簽發者的中繼資料端點取得正確的 JWK 來驗證 token。
實作:可用於生產環境的程式碼
PHP 搭配 lcobucci/jwt
PHP 生態系的標準選擇是 lcobucci/jwt。根據 Packagist 的資料,截至 2026 年 4 月已累積超過 322 million 次安裝,是 Laravel 與 Symfony 專案的首選。
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
$config = Configuration::forSymmetricSigner(
new Sha256(),
InMemory::plainText('your-secret-key')
);
// Parsing and validating a token
$token = $config->parser()->parse($jwtString);
// Verify constraints: expiration, issuer, etc.
$constraints = [
new \Lcobucci\JWT\Validation\Constraint\IssuedBy('auth.example.com'),
new \Lcobucci\JWT\Validation\Constraint\PermittedFor('api.example.com'),
new \Lcobucci\JWT\Validation\Constraint\SignedWith(
$config->signer(),
$config->signingKey()
),
];
$isValid = $config->validator()->validate($token, ...$constraints);
Hono(Edge/Serverless)搭配 Web Crypto
對於輕量級的邊緣應用,Hono JWT Helper 提供了極簡的 decode() 函式,非常適合需要快速冷啟動與最少相依套件的 serverless 平台。
import { jwt } from 'hono/jwt'
// Middleware to verify JWT on every request
app.use('/api/*', jwt({ secret: 'your-secret' }))
// Access decoded claims in your handler
app.get('/api/profile', (c) => {
const payload = c.get('jwtPayload')
return c.json({ user: payload.sub })
})
用 MCP 進行 AI 驅動的 JWT 分析
到了 2026 年,Model Context Protocol(MCP) 讓 Claude Code 或 Cursor 這類 AI 助理能直接與 JWT 工具溝通。設定好 MCP server 後,開發者就能要求 AI「檢查這些 log 中所有 JWT 是否有過期錯誤」——代理程式會透過命令列處理解析工作。
根據 Apify 的資料,截至 2026 年,大量處理的成本約為每 10,000 個 token $11.50。這種自動化能讓 AI 代理找出過期的 token,並立即針對應用程式的安全設定建議程式碼修正。
結論
JWT 解析器不只是除錯的便利工具——它是關鍵的安全檢查點。它透過簽章檢查確保 token 真實,並透過聲明驗證確保 token 有效。請記住兩條最重要的規則:Base64URL 不是加密,所以絕不要把機密放進 payload。並且永遠要明確指定允許的演算法,以防止「alg: none」攻擊。
對於生產環境的應用程式,請使用 lcobucci/jwt 或 Hono 的 JWT helper 這類經過驗證的函式庫,而不要自己打造解析器。至於除錯與大量分析,AI 驅動的 MCP 工具是讓安全稽核保持自動化且徹底的現代做法。
FAQ
解碼我在瀏覽器中找到的 JWT token 合法嗎?
合法,完全合法。JWT 的設計本身就是透明的——header 與 payload 是為了傳輸而編碼,並非為了保密而加密。擁有 token 即表示你有權存取其聲明中的資料。不過,當 token 含有個人資訊時,請務必遵守 GDPR 等當地的資料保護法規。
為什麼我剛產生的 token,JWT 解析器卻顯示 isExpired: true?
這通常是因為產生 token 的伺服器與解析 token 的系統之間出現時鐘漂移(clock drift)。若兩個系統的時鐘未同步(透過 UTC/NTP),exp 或 nbf 聲明可能會顯得無效。修正方式是確保兩個系統都使用 NTP 進行時間同步,或在你的解析函式庫中加入小幅「容差(leeway)」(通常為 60 seconds),以吸收微小的偏差。
沒有密鑰或公鑰,我可以解碼 JWT 嗎?
可以,你永遠可以在沒有金鑰的情況下解碼並讀取 Header 與 Payload,因為它們只是 Base64URL 編碼的 JSON。然而,若沒有對應的密鑰(HS256 用)或公鑰(RS256 用),你無法驗證 Signature,也無法信任資料的真實性。在未驗證的情況下,請將資料視為未經驗證、且可能已遭竄改。
什麼是「alg: none」攻擊,我該如何防範?
「alg: none」攻擊利用的是會直接接受 token header 中指定演算法、卻不加以驗證的解析器。攻擊者把 header 改成 "alg": "none" 並移除簽章,誘騙有漏洞的解析器把 token 當成有效。防範方式是在驗證程式碼中永遠明確指定允許的演算法——絕不接受「none」,也絕不讓 token 自己決定要使用哪個演算法。