Session Management
Vibe Prompt
「幫我實作安全的 Session 管理:HTTP-only、Secure、SameSite Cookie,Session 儲存在 Redis。」
安全 Cookie 設定
// Express
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true, // JavaScript 無法讀取
secure: true, // 僅 HTTPS
sameSite: 'strict', // 防止 CSRF
maxAge: 24 * 60 * 60 * 1000, // 24 小時
},
}));
Redis Session Store
import Redis from 'ioredis';
import session from 'express-session';
import RedisStore from 'connect-redis';
const redis = new Redis({
host: process.env.REDIS_HOST,
port: 6379,
password: process.env.REDIS_PASSWORD,
});
app.use(session({
store: new RedisStore({ client: redis }),
secret: process.env.SESSION_SECRET,
cookie: {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 86400000,
},
}));
Session Fixation 防護
// 登入後重新生成 Session ID
app.post('/login', async (req, res) => {
const user = await authenticate(req.body);
if (user) {
req.session.regenerate((err) => {
req.session.userId = user.id;
res.json({ success: true });
});
}
});
關鍵要點
- ✅ 請根據本章主題補充具體的學習重點
- ✅ 建議加入比較表格、程式碼範例或流程圖
- ✅ 確保內容扎實且有價值
Session 攻擊與防禦
Session Hijacking(劫持)
攻擊者竊取使用者的 Session ID 來冒充身分。
| 攻擊方式 | 說明 | 防禦措施 |
|---------|------|---------|
| 側錄網路封包 | 在公共 WiFi 監聽 HTTP 流量 | 強制 HTTPS + HSTS |
| XSS 偷取 Cookie | 透過 XSS 讀取 document.cookie | HttpOnly + Secure Cookie |
| Session 固定 | 讓使用者使用攻擊者指定的 Session ID | 登入後重新產生 Session ID |
| 暴力猜測 | 猜測弱 Session ID | 使用高熵值的亂數 |
Session 安全設定
// Express.js Session 設定
app.use(session({
name: "__Host-session", // 前綴確保 Cookie 安全
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true, // 禁止 JavaScript 讀取
secure: true, // 僅透過 HTTPS 傳送
sameSite: "lax", // CSRF 防護
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 天
}
}));
JWT vs Session
| 比較 | JWT (Stateless) | Session (Stateful) | |------|:---------------:|:------------------:| | 儲存位置 | 客戶端 Cookie | 伺服器端資料庫/Redis | | 可撤銷性 | ❌ 發出後無法撤銷 | ✅ 立即刪除 Session | | 擴展性 | ✅ 不需要共享儲存 | ⚠️ 需要共用 Session 儲存 | | 安全性 | 需注意 JWT 簽章 | Session ID 是亂數更安全 |
Session 管理的核心:JWT vs Session
很多開發者會問:「到底要用 JWT 還是 Session?」
答案是:看你的需求。
| 比較 | JWT (無狀態) | Session (有狀態) | |:----:|:-----------:|:---------------:| | 儲存位置 | 客戶端 Cookie | 伺服器端(Redis / 資料庫) | | 可撤銷性 | ❌ 發出後無法單方面撤銷 | ✅ 立即刪除 Session 即可 | | 擴展性 | ✅ 不需要共享儲存 | ⚠️ 需要共用 Redis/DB | | 安全性基礎 | 簽章演算法(需保護密鑰) | Session ID 是亂數,更安全 | | 大小 | 較大(包含 Payload) | 極小(只是一個亂數 ID) | | 適合場景 | API 授權、微服務、跨站認證 | 傳統網頁應用、需要立即撤銷權限 |
常見的 Session 攻擊
| 攻擊 | 手法 | 防禦 |
|:----:|:----:|:----:|
| Session Hijacking | 竊取 Session Cookie | HttpOnly + Secure + SameSite |
| Session Fixation | 讓使用者使用攻擊者指定的 Session ID | 登入後重新產生 Session ID |
| 暴力猜測 | 嘗試猜測 Session ID | 使用高熵值的亂數 ID |
| XSS | 透過 XSS 讀取 Cookie | HttpOnly Cookie |
| CSRF | 利用已登入的 Session 執行惡意操作 | SameSite Cookie + CSRF Token |
下一章預告:從 Session 到 PKCE
Session 和 JWT 都是傳統的認證方式。但對於 SPA(單頁應用)和手機 App,有更好的選擇——PKCE (Proof Key for Code Exchange)。
下一章將深入 OAuth 2.0 的 PKCE 流程,這是你開發現代化 App 和 SPA 時必須掌握的認證技術。