JWT 不是 Session Cookie,別再搞混了
你很可能已經用過 JWT。 可能是為了用戶認證; 也可能是因為有人對你說:“兄弟,它是無狀態的,能橫向擴展,賊香。”
于是你就像往面條里加辣椒油一樣,給所有場景都撒上了 JWT:
- 登錄認證?JWT
- API 會話?JWT
- 開鎖?呃……可能也想用 JWT ??♂?
但真相是——JWT 雖然強大,卻也非常容易被濫用。
今天帶你看看 JWT 到底是什么,底層怎么運作,在哪些場景是神兵利器,哪些場景卻是大坑。
JWT 到底是個啥?
本質上,JWT(JSON Web Token)就是一個 加了數字簽名的短字符串。
它是一個體積小、URL 安全、能防篡改的 JSON 數據包。
想象一下,它就像一個防篡改的信封: 你可以打開看看內容,但要是想偷偷改幾個字?抱歉,會被立刻發現。
一個 JWT 的結構長這樣(來自 jwt.io):
- Header(使用的簽名算法)
- Payload(數據)
- Signature(防篡改的簽名)
三部分用 Base64 編碼,再用 . 分隔,組合成一個看起來很酷的字符串。
來,自己做一個
Node.js + jsonwebtoken 庫,老朋友了:
const jwt = require('jsonwebtoken');
const token = jwt.sign({ userId: 123 }, process.env.JWT_SECRET, { expiresIn: '15m' });
console.log(token);然后把它發給客戶端,客戶端在每個請求的 Authorization 頭里帶上它:
Authorization: Bearer <token>服務端這樣驗證:
jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });看起來很優雅……直到不優雅。
常見的坑(我全踩過)
1. 把 JWT 當成 Session
JWT 的賣點是“無狀態”,服務端不存儲它,所以理論上擴展性好。
問題來了:
- 用戶登出怎么辦?
- 想要撤銷某個已發出的 token 呢?
抱歉,JWT 發出去,就會一直有效到過期,除非你額外維護一個黑名單——但那樣就失去了“無狀態”的意義。
解決方案:短過期時間 + 存在安全的刷新 token(推薦 HttpOnly Cookie)。
2. 把 Payload 塞成個皮納塔(糖果球)
JWT 不是加密的,只是編碼了。 任何人用在線工具都能在 5 秒鐘解碼。
所以別往 payload 里塞敏感數據,比如: ? 密碼 ? 郵箱 ? 權限細節
3. 算法配置馬虎
早期有個著名漏洞:某些庫會接受 "alg": "none",等于“簽名?不存在的”。
就好像你鎖了門,但在門口貼了個紙條:“鑰匙在腳墊下”。
安全寫法:
jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });JWT 適合 vs 不適合的場景
? 適合:
- 微服務架構,各服務獨立驗證用戶身份
- 移動 App / SPA(React、Vue)不想依賴傳統 Cookie
- API 橫向擴展,避免維護集中式 Session
? 不適合:
- 傳統服務端渲染 Web 應用
- 對“立即注銷/撤銷”有高要求的系統
- 對帶寬敏感(JWT 比 session ID 大很多)
一個比喻幫你秒懂
JWT 像護照: 自包含、帶簽名、不用查中央數據庫就能驗證真假(除非過期或被偷)。
Session ID 像健身房儲物柜的鑰匙: 儲物柜(會話)放在服務端,鑰匙只是個引用。
血淚教訓
我們曾做過一個內部管理后臺,功能很簡單,用了 JWT,因為“大家都在用”。 結果忘了輪換 token,也沒用 HttpOnly Cookie,用戶能登錄幾周都不掉線。
最終不得不重寫登錄流程,加上刷新 token 系統。
教訓:JWT 不是“一次集成,永久無憂”。
快速安全建議
- 密鑰放環境變量,不要硬編碼
- 全程用 HTTPS
- 過期時間控制在 15 分鐘左右,然后用刷新 token
- 除非萬不得已,不要把 JWT 放 localStorage,優先 HttpOnly Cookie
總結: JWT 是個好工具,但不是萬能鑰匙。用對場景,它能讓你的系統更靈活;用錯場景,它會變成隱患制造機。
別盲信教程,理解原理才能避坑。 不然,下一次凌晨 2 點在 Slack 群里慌的,可能就是你。
































