動詞實驗室 Logo動詞實驗室

【後端架構系列 01】驗證演化論:從 Session 到 JWT 的技術博弈

發布於 閱讀時間 6 分鐘

01. 前言:別為了技術而技術

在 2026 年的今天,當一個後端工程師被問到:「如何實作登入功能?」時,90% 的人會不假思索地回答:「用 JWT (JSON Web Token) 啊!」

彷彿 JWT 是解決所有驗證問題的銀彈,而 Session/Cookie 則是上個世紀的遺毒。這種現象在 Node.js 社群尤為明顯,npm install jsonwebtoken 幾乎成了起手式。

但筆者必須說:這是一種危險的「技術跟風」。

許多開發者在擁抱 JWT 的同時,並不理解它為了「無狀態 (Stateless)」犧牲了什麼。為什麼銀行的網銀系統大多還是堅持用 Session?為什麼你的 JWT 讓使用者改了密碼卻還能繼續瀏覽?

這系列文章,我們不只教你怎麼寫 Code,更要教你怎麼「選型」。第一篇,我們從架構演進的角度,來一場 Session 與 JWT 的深度博弈。

02. 傳統霸主:Session Based Authentication

在 Web 發展的早期,伺服器大多是單體架構 (Monolithic)。這時期的驗證邏輯非常直觀,我們可以把它想像成**「健身房的櫃檯制」**。

運作機制:Stateful (有狀態)

  1. 報到:使用者輸入帳號密碼(出示證件)。
  2. 紀錄:Server 驗證通過後,產生一個 Session ID,並在 Server 的記憶體或資料庫(Redis)中開一個空間,紀錄「這個 ID 對應到 User A,登入時間是 10:00」。
  3. 給憑證:Server 透過 HTTP Header Set-Cookie,把這個 Session ID 交給瀏覽器。
  4. 通行:之後瀏覽器每次發送 Request,都會自動帶上這個 Cookie。Server 拿到 ID,去記憶體翻找紀錄,確認身分。

Session 的致命傷:擴展性 (Scalability)

這個機制在單一台 Server 時運作完美。但在現代高流量時代,我們通常會部署多台 Server 做負載平衡 (Load Balancing)。

筆者情境模擬: 使用者小明在 Server A 登入了,Session 存在 Server A 的記憶體裡。 下一秒,負載平衡器把小明的請求導到了 Server B。 Server B 一臉茫然:「你是誰?我的記憶體裡沒有你的資料。」-> 小明被強制登出。

雖然我們可以用 Redis 來集中管理 Session (Sticky Session 或 Distributed Session),但這意味著每次 Request 都要多一次網路 I/O 去查 Redis,這在高併發場景下是一筆不小的開銷。

03. 挑戰者:Token Based Authentication (JWT)

為了解決擴展性問題,JWT 應運而生。它的核心思想是**「以時間換取空間」「信任簽章」。我們可以把它想像成「遊樂園的 VIP 手環」**。

運作機制:Stateless (無狀態)

  1. 簽發:使用者登入。Server 不再紀錄「誰來了」,而是把用戶資訊(ID, Role, Expiration)打包,用 Server 獨有的「私鑰」進行加密簽章。
  2. 持有:Server 把這個簽章過的字串 (Token) 丟給 Client。Server 自己不存這份資料。
  3. 驗證:Client 每次 Request 都在 Header (Authorization: Bearer <token>) 帶上 Token。
  4. 通行:Server 收到 Token,用數學演算法驗證簽名。只要簽名沒被改過且沒過期,Server 就無條件信任裡面的內容。

JWT 的核心公式

JWT 的安全性並非來自「加密」(因為 Payload 只是 Base64 編碼,誰都能看),而是來自「簽章 (Signature)」。

$$Signature = HMACSHA256(base64(Header) + "." + base64(Payload), SecretKey)$$

只要駭客不知道 Server 的 SecretKey,他就無法篡改 Payload 裡的 role: "admin",因為一旦改了,算出來的 Signature 就會跟尾段不符,Server 直接拒絕。

04. 深度博弈:技術決策矩陣

這是本篇最硬核的部分。我們不談空泛的理論,直接從資源消耗與安全邊界來比較。

特性Session (Cookie)JWT (Token)筆者點評
狀態性 (State)Stateful<br>Server 握有絕對控制權。Stateless<br>信任與驗證機制。這是所有差異的根源。
Server 負載I/O 密集<br>每次 Request 都要查 DB/Redis。CPU 密集<br>每次 Request 都要進行解密/雜湊運算。Node.js 單執行緒不適合大量 CPU 運算,但查 Redis 的網路延遲通常影響更大。
水平擴展性差 (需額外處理)<br>需引入 Redis Cluster。極佳<br>任意 Server 拿到 Key 都能驗證,無需同步。微服務 (Microservices) 架構的首選。
頻寬消耗極小<br>只傳輸一個短字串 ID。較大<br>包含 Header+Payload+Sig,越長越佔頻寬。在 Mobile 弱網環境下需注意 Token 大小。
可控性 (Revoke)高 (即時)<br>想踢人,刪除 Server 端資料即可。低 (延遲)<br>Token 發出後,在過期前都有效。這是 JWT 最大的痛點。

筆者深度解析:JWT 的「無法撤銷」難題

這是面試中最常被問到的陷阱題:「如果使用 JWT,當使用者手機遺失或被盜號,我要怎麼強制他登出?」

在純粹的 JWT 機制下,答案是:做不到。 因為 Server 端根本沒存「誰登入了」。一旦 Token 發出去,就像潑出去的水。

解法?

  1. 黑名單 (Blacklist):把要踢掉的 Token 存進 Redis。 (等等,這樣不就又變回 Stateful 且要查 Redis 了嗎?)
  2. 短效期 Access Token + Refresh Token:這是業界標準解法,我們將在 Ep.3 實作。

05. 實戰場景:你該怎麼選?

別被「JWT 是新技術」給騙了。在選擇架構時,請依據你的業務場景決定:

✅ 適合使用 Session 的場景

  • 銀行、金融系統、企業內部後台:安全性要求極高,管理員需要有「一鍵踢人」的權限。
  • 使用者人數可控:例如只有幾千人的內部系統,Redis 的負載完全不是問題。
  • 傳統 MVC 架構:前後端未分離,Server 直接 Render HTML。

✅ 適合使用 JWT 的場景

  • 對外公開的 API (Open API):給第三方開發者使用。
  • 微服務架構 (Microservices):多個 Service 之間需要傳遞使用者身分,JWT 可以避免每個 Service 都要去查一次 Redis。
  • Mobile App / Single Page App (SPA):需要跨網域、跨裝置,且 Cookie 操作較為受限的環境。
  • 短期活動網站:流量可能瞬間爆發,需要極致的水平擴展能力。

06. 結論:沒有最好的架構,只有最合適的權衡

JWT 是一個強大的工具,但它不是免死金牌。它帶來了擴展性的紅利,卻也帶來了「狀態管理」的債務。

在下一篇 【Ep.2:拆解 JWT - 結構、原理與 Node.js 實作】 中,我們將脫離理論,直接進入程式碼層面。筆者將帶你手寫一個安全的 JWT 簽發流程,並示範如何避免常見的「None Algorithm」攻擊與敏感資訊洩漏陷阱。

準備好你的 IDE,我們下一篇見。


我相信技術的價值在於解決問題,而不是盲目追求潮流。如果你對 API 驗證有獨到的見解,歡迎在下方留言交流。


Ken Huang

關於作者

Ken Huang

擁有超過 9 年軟體開發經驗的資深工程師,現任 APP 工程師,專精於 Android / iOS 雙平台開發。同時持續拓展後端與雲端技術範疇,致力於朝向全端架構師的領域邁進。

具備完整的專案生命週期實戰經驗:

  • 新創開發:主導多個從零到一的新專案規劃、技術選型與開發落地。
  • 系統維護與重構:擁有維護與升級 10 年以上大型歷史專案(Legacy Code)的豐富經驗,擅長進行代碼重構與效能優化。

身為知名 PTT 第三方 APP BePTT 的開發者,致力於將 Clean Architecture、Scrum 敏捷開發與現代化軟體工程原則應用於產品中,打造極致的使用者體驗。

verb.tw 是我紀錄技術軌跡與架構思考的基地,內容涵蓋 App 開發實戰、全端技術整合與軟體工程最佳實踐。

Senior App EngineerAndroid/iOS ExpertBePTT CreatorSystem Architecture