「Authentication:你是誰?Authorization:你能做什麼? 很多安全漏洞來自於混淆這兩個問題,或者實作其中一個時忘記另一個。」
從傳統的 Session-Cookie,到 JWT Token,到現在普遍的 OAuth2 第三方登入—— 每種方案都有它的設計取捨。理解原理,才能在不同場景做出正確選擇。
認證 vs 授權:先搞清楚概念
Authentication(認證)
你是誰?驗證身份的過程。
就像進辦公室時門禁刷卡——系統確認「這是員工 Joseph」。
• 帳號密碼登入
• Google / GitHub 第三方登入
• 手機簡訊 OTP
• 生物辨識(Face ID)
Authorization(授權)
你能做什麼?在確認身份後,確認你有沒有權限執行特定操作。
就像進了辦公室後,只有 HR 能開薪資系統。
• 角色控制(RBAC):admin / user / guest
• 資源所有者:只能刪自己的文章
• API Scope:只能讀取,不能寫入
Session-Cookie:傳統有狀態認證
Session-Cookie 是最傳統的 Web 認證方式。伺服器「記住」使用者的登入狀態,存在記憶體或 Redis 中。
Session-Cookie 流程
Set-Cookie 的三個安全屬性
HttpOnly禁止 JavaScript 讀取 Cookie(document.cookie)。防止 XSS 攻擊竊取 Session ID。Secure只在 HTTPS 連線時傳送 Cookie。防止明文傳輸被中間人竊聽。SameSite=Strict跨站請求(CSRF)不帶 Cookie。Strict:完全禁止跨站帶;Lax(推薦):允許從外部連結導入,但阻止 POST 跨站請求。以上三者應同時設定。省略任何一個都可能留下安全漏洞。
✅ Session 的優點
- • 可以立即撤銷(刪除 Redis 中的 Session)
- • 敏感資料存在伺服器端,不暴露給客戶端
- • 瀏覽器自動管理 Cookie,不需要前端處理
❌ Session 的缺點
- • 有狀態(Stateful),水平擴展需要共享 Session 存儲
- • CSRF(跨站請求偽造)攻擊的目標
- • 不適合 API / 行動 App(Cookie 是瀏覽器限定)
JWT:無狀態的 Token 認證
JWT(JSON Web Token)把使用者資訊編碼在 Token 本身,伺服器不需要儲存 Session—— 只需要驗證 Token 的簽名是否有效。
JWT 結構:三段 Base64 用「.」分隔
Header(紅色)
{
"alg": "HS256",
"typ": "JWT"
}Payload(藍色)
{
"id": 1,
"email": "...",
"exp": 1700000000
}Signature(綠色)
HMACSHA256(
base64(header) + "." + base64(payload),
SECRET_KEY)
⚠️ Payload 只是 Base64 編碼(不是加密),任何人都能解碼看到內容!不要放敏感資料(密碼、卡號)。
Refresh Token 撤銷:Redis 黑名單
JWT 一旦簽發就無法撤銷(直到過期)。若使用者登出或帳號被停用, Access Token 15 分鐘後才會失效。需要撤銷 Refresh Token 來防止換新 Token。
JWT 最常見的錯誤
- • 存在 localStorage:容易被 XSS 竊取,改用記憶體(React state)+ Refresh Token in HttpOnly Cookie
- • 存活期太長:Access Token 應該短(15min),搭配 Refresh Token 延續 session
- • Payload 放密碼:Payload 只是 Base64,任何人都能解碼
- • 忘記處理過期:前端要捕捉 401,自動用 Refresh Token 換新 Access Token
OAuth2:第三方登入的標準流程
OAuth2 是「授權委派」協定——讓使用者授權你的應用存取他在 Google / GitHub / Facebook 的資料, 而不需要把密碼給你。「使用 Google 登入」就是 OAuth2 的 Authorization Code Flow。
OAuth2 Authorization Code Flow(最安全的流程)
⚠️ OAuth2 和 Session / JWT 的關係
OAuth2 解決的是「使用者授權第三方存取其帳號」的問題——它本身不規定你要用 Session 還是 JWT。 第⑥步 NextAuth 拿到 Google 的使用者資料後,你的 App 自己決定要簽發 Session(存 Redis)還是 JWT。 NextAuth 預設使用加密的 Session Cookie(本質是 JWT),你也可以換成 Database Adapter 改用 Redis Session。
Session vs JWT:怎麼選?
| Session-Cookie | JWT | |
|---|---|---|
| 有無狀態 | Stateful(需要 Redis) | Stateless(伺服器不存資料) |
| 水平擴展 | 需要共享 Session Store | ✅ 任一台伺服器都能驗證 |
| 立即撤銷 | ✅ 刪 Redis 即時生效 | ❌ 需等 Token 自然過期(或黑名單) |
| 適合場景 | Web 應用(傳統 MVC) | API、行動 App、微服務 |
| CSRF 風險 | 有(Cookie 自動帶上) | 無(需手動帶 Header) |
| XSS 風險 | 低(HttpOnly Cookie) | 高(若存 localStorage) |
實務建議
傳統 Web App(Next.js SSR):用 NextAuth.js,它幫你管理 Session-Cookie,簡單安全。
Pure API / 行動 App:用 JWT(短存活 Access Token + HttpOnly Cookie 的 Refresh Token)。
第三方登入:不要自己實作 OAuth2,用 NextAuth.js / Auth.js / Clerk 等成熟方案。