JWT 解析器指南:如何安全地解碼、驗證與檢視 JSON Web Token

JWT 解析器指南:如何安全地解碼、驗證與檢視 JSON Web Token

3 min read

你的生產環境驗證突然掛了。使用者一直收到「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 否——需要金鑰

JWT token 簡化的三段式結構

逐步解碼:內部發生了什麼

讓我們追蹤一個真實的 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 模式相同但採橢圓曲線 金鑰更小、驗證更快 行動應用、對效能敏感的服務

JWT 解析器的三步驟驗證邏輯

「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),expnbf 聲明可能會顯得無效。修正方式是確保兩個系統都使用 NTP 進行時間同步,或在你的解析函式庫中加入小幅「容差(leeway)」(通常為 60 seconds),以吸收微小的偏差。

沒有密鑰或公鑰,我可以解碼 JWT 嗎?

可以,你永遠可以在沒有金鑰的情況下解碼並讀取 Header 與 Payload,因為它們只是 Base64URL 編碼的 JSON。然而,若沒有對應的密鑰(HS256 用)或公鑰(RS256 用),你無法驗證 Signature,也無法信任資料的真實性。在未驗證的情況下,請將資料視為未經驗證、且可能已遭竄改。

什麼是「alg: none」攻擊,我該如何防範?

「alg: none」攻擊利用的是會直接接受 token header 中指定演算法、卻不加以驗證的解析器。攻擊者把 header 改成 "alg": "none" 並移除簽章,誘騙有漏洞的解析器把 token 當成有效。防範方式是在驗證程式碼中永遠明確指定允許的演算法——絕不接受「none」,也絕不讓 token 自己決定要使用哪個演算法。

About the author

SE

SectoJoy

Creator of Ez Parser, focused on practical parser and decoder workflows.

Follow author