TL;DR | 面試情境模擬 #
👴 面試官:JWT 和 Session 有什麼差別?各自適合什麼場景?
🧑💻 你:Session 把登入狀態存在 Server 端(通常是 Redis),客戶端只持有一個 Session ID。JWT 把所有資訊編碼在 Token 本身,Server 驗證簽章就好,不需要查資料庫。Session 容易撤銷但需要共享 Session Store;JWT 天生無狀態適合微服務,但 Token 一旦發出就很難在過期前撤銷。
比喻:儲物櫃鑰匙 vs 身份證 #
- Session:像儲物櫃鑰匙。你拿著號碼牌(Session ID),服務員去後台查你的資料。服務員可以隨時取消你的資格(刪 Session)。
- JWT:像身份證。上面直接印了你的名字、年齡、有效期。別人看一眼就知道你是誰,不需要去查名冊。但如果這張身份證被偷了,在它過期之前你沒辦法讓它失效。
運作流程對比 #
Session 流程 #
登入:
Client ─── POST /login ──────────────────> Server
Server ─── 建立 Session,存入 Redis ──────>
Server ─── Set-Cookie: session_id=abc123 -> Client
之後每次請求:
Client ─── Cookie: session_id=abc123 ────> Server
Server ─── 查 Redis:abc123 是誰? ───────>
Server ─── 確認,處理請求 ───────────────> Client
JWT 流程 #
登入:
Client ─── POST /login ──────────────────> Server
Server ─── 用私鑰簽署 JWT ───────────────>
Server ─── 回傳 JWT ─────────────────────> Client
之後每次請求:
Client ─── Authorization: Bearer <jwt> ──> Server
Server ─── 驗證簽章 + 確認未過期 ─────────>(不查 DB)
Server ─── 處理請求 ─────────────────────> Client
JWT 結構 #
JWT 由三段 Base64 編碼組成,用 . 分隔:
header.payload.signature
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxMjMifQ.SflKxwRJSMeKKF2QT4f
- Header:指定簽章演算法(如 HS256、RS256)
- Payload:存放 userId、角色、過期時間等(明文,不要放敏感資料)
- Signature:用密鑰對 header + payload 簽章,防止竄改
核心比較 #
| 特性 | Session | JWT |
|---|---|---|
| 狀態儲存位置 | Server(Redis / DB) | Client(Token 本身) |
| Server 負擔 | 需要儲存 + 查詢 | 無狀態,只驗簽章 |
| 撤銷能力 | 容易(刪 Session) | 困難(需要黑名單) |
| 擴展性 | 需要共享 Session Store | 天生適合多服務 |
| 適合場景 | 傳統 Web、需要即時登出 | API、微服務、SPA |
💡 面試官可能會追問 #
Q1:JWT 的安全陷阱有哪些? #
- Payload 不加密:任何人都能 Base64 decode 看到內容,不要放密碼或敏感資料
- alg: none 攻擊:某些函式庫接受
"alg": "none"跳過簽章驗證,一定要在 Server 端指定允許的演算法 - Token 無法撤銷:用戶登出後 Token 在過期前仍然有效,需要維護黑名單或使用短 expiry + refresh token
Q2:Refresh Token 是什麼? #
因為 Access Token 時效要短(降低被盜的風險,通常 15 分鐘到 1 小時),到期後用 Refresh Token(存在 Server)換新的 Access Token,達到「長時間登入」同時「Access Token 短命」的平衡。
Q3:什麼時候該用 Session,什麼時候用 JWT? #
- Session:傳統 Web app、需要即時踢人、對安全要求高(銀行、金融)
- JWT:REST API、微服務架構、前後端分離的 SPA、第三方 API 授權