哈囉,我1010

Hello, LARQFTN

回列表

為什麼現在大家都用 JWT?淺談 Session 與 Token 的恩怨情仇

大家現在寫後端 API,只要碰到登入驗證,起手式幾乎都是直接發一張 JWT (JSON Web Token)。

但你有沒有想過,以前我們用 Session + Cookie 明明就用得好好的,為什麼到了「前後端分離」和「微服務」的時代,大家卻好像講好了一樣,紛紛把 Session 打入冷宮?

今天就來聊聊,傳統的 Session 到底踩到了什麼痛點,而 JWT 又是怎麼像救世主一樣解決這些問題的(當然,我們也會扒一扒 JWT 的缺點)。


🏛️ 以前的美好年代:Session + Cookie 是怎麼運作的?

傳統的 Session 機制,概念就像是一間會員制俱樂部

  1. 登入: 你走到門口,把帳號密碼交給警衛(Server)。
  2. 紀錄: 警衛確認無誤後,會在他的**小本本(伺服器記憶體)**裡記下「User A 已登入」,然後發給你一個號碼牌(Session ID)。
  3. 發送號碼牌: 這個號碼牌通常會偷偷塞進你的瀏覽器 Cookie 裡。
  4. 下次光臨: 之後你每次發 Request,瀏覽器都會自動帶著這個 Cookie。警衛看到號碼牌,翻一下小本本對照,就知道「喔!你是 User A,請進。」

這套機制很安全,也很直覺。但當我們的系統開始長大,噩夢就來了。


💥 危機降臨:當架構變成「前後端分離」與「微服務」

隨著時代進步,我們的系統架構發生了兩件大事,直接把 Session 機制逼到了牆角:

1. 前後端分離帶來的 CORS 跨網域地獄

現在的前端可能是 Vue 或 React (跑在 localhost:5173),後端是 FastAPI (跑在 localhost:8000)。因為網域不同,瀏覽器基於安全考量,預設是不會幫你跨網域攜帶 Cookie 的。為了解決這個設定,前端跟後端都要花一堆力氣去搞定 withCredentials 和 CORS 標頭,超級心累。

2. 微服務架構的「失憶症」

假設你的網站爆紅,一台伺服器撐不住,於是你開了三台機器 (Server A, B, C) 來分流。 這下尷尬了:你昨天在 Server A 登入,警衛 A 在他的小本本記下了你。今天負載平衡器把你分配給 Server B,結果警衛 B 的小本本裡根本沒有你!他只會冷冷地回一句:「你誰?請重新登入。」(401 Unauthorized)。

為了解決這個問題,工程師只好弄一台獨立的 Redis 資料庫,叫所有警衛統一去那邊查名單。雖然解決了,但系統架構也變得越來越笨重。


🦸‍♂️ 救世主降臨:無狀態的 JWT (JSON Web Token)

為了解決 Server 必須「死記硬背」使用者狀態的痛點,Token 驗證機制(尤其是 JWT)誕生了。

JWT 的概念不是發號碼牌,而是直接發給你一張防偽員工證

  1. 登入: 你給 Server 帳號密碼。
  2. 簽發證件: Server 驗證成功後,把你的使用者 ID、權限、過期時間寫在一張卡片上,然後在最後面蓋上一個獨一無二的數位簽章 (Signature)
  3. 交給客戶端: Server 把這張卡片(JWT)交給你,然後 Server 就把你忘了(這就是所謂的 Stateless 無狀態)。
  4. 下次光臨: 你發 Request 時,把 JWT 放在 Header (Authorization: Bearer <token>) 裡遞給 Server。Server 根本不需要翻小本本,他只要用自己的密鑰檢查那個「數位簽章」是不是真的。如果是真的,且沒過期,就直接放行!

這樣一來,不管後端開了幾百台機器,只要大家的「密鑰」是一樣的,誰都能驗證這張 JWT,完美解決了微服務的擴展問題!而且 Token 通常放在 Header 裡,也順手避開了 Cookie 跨網域的雷坑。


🛑 醒醒吧,JWT 不是萬靈丹(缺點大公開)

聽起來 JWT 超棒對吧?但天下沒有白吃的午餐,它其實也有幾個讓人頭痛的致命傷:

1. 潑出去的水,收不回來(無法輕易註銷)

因為 Server 不記仇(無狀態),如果使用者的 Token 被盜,或是管理員想把某個作弊玩家踢下線,Server 是做不到的! 除非 Token 自動過期,否則那張通行證永遠有效。 如果要硬解,就得在後端建一個「黑名單庫(Blacklist)」——等等,這不就又回到 Session 查表的老路了嗎?

2. 佔用頻寬的胖子

Session ID 短短幾十個字元,但 JWT 裡面包了 Header、Payload 跟 Signature,動輒幾百字元。每次發 API 都要帶著這個大胖子,其實挺佔網路頻寬的。

3. 拜託,裡面別放機密資料!

JWT 中間那段 Payload 只是簡單的 Base64 編碼,任何人拿到都能輕鬆解碼看見裡面的內容。它只能防篡改(因為有簽章),不能防偷看。千萬別把使用者的密碼或身分證字號塞進 JWT 裡!


🍻 總結

技術選型從來就沒有「絕對的好壞」,只有「適不適合」。

如果你的專案只是個傳統的單體式網站,沒有跨網域需求,Session 其實超級安全又好管理。但如果你正在開發的是前後端分離的現代化 Web App,或是打算做 App 版本的 API,那 JWT 絕對是你目前最好的選擇

理解了這些底層恩怨情仇,下次有人問你「為什麼要用 JWT?」的時候,你就不用只會回答「因為教學文章都這樣寫」了!😎