博客 / 詳情

返回

面試官:説説看,用户登錄後拿到的 Token,你應該怎麼存?存哪裏?

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

開篇:一個經典的面試題

“説説看,用户登錄後拿到的 Token,前端應該怎麼存?”

這個問題看似簡單,卻能清晰地分辨出一個前端開發者對安全的理解深度。是存到 localStoragesessionStorage?還是 Cookie?又或者是內存裏?不同的選擇背後,是截然不同的安全考量。

今天,來聊一聊 Token 的存儲之道,讓你不僅知道怎麼做,更明白為什麼這麼做。

ScreenShot_2026-01-14_093508_484

選項一:Web Storage(localStorage / sessionStorage

這是最直觀、最容易想到的方案。

// 登錄成功後
const token = 'your_jwt_token_here';
localStorage.setItem('auth_token', token);

// 後續請求時帶上
axios.interceptors.request.use((config) => {
  const token = localStorage.getItem('auth_token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

優點:

  • 簡單易用:API 簡單,上手快。
  • 永久存儲localStorage):除非手動清除,否則一直存在。
  • 會話期存儲sessionStorage):頁面關閉即清除,更安全一點。

致命缺點:

  • 極易受到 XSS (跨站腳本攻擊) 的攻擊。這是最核心的問題。如果網站存在 XSS 漏洞,攻擊者的惡意腳本可以輕易地讀取到 localStorage 中的所有 Token,從而竊取用户身份。

結論: 不推薦,尤其對於敏感應用。 除非你的應用完全不存在 XSS 風險(但這幾乎不可能),或者 Token 的安全級別要求不高。

選項二:Cookie

Cookie 是傳統且常見的身份驗證載體。

// 服務端設置 Cookie (HTTP Response Header)
Set-Cookie: auth_token=your_jwt_token_here; Path=/; HttpOnly; Secure

// 前端無需特殊處理,瀏覽器會自動在每次請求中攜帶

注意這裏的兩個關鍵屬性:

  • HttpOnly這是對抗 XSS 的神器。設置了 HttpOnly 的 Cookie 無法通過 JavaScript 的 document.cookie API 訪問,這意味着即使發生 XSS,攻擊者也無法竊取到 Token。
  • Secure:強制 Cookie 只能在 HTTPS 協議下被髮送,防止在網絡傳輸中被竊聽。

優點:

  • 免疫 XSS(得益於 HttpOnly):無法通過 JS 讀取,安全性高。
  • 可控制生命週期:通過 ExpiresMax-Age 設置過期時間。
  • 自動管理:瀏覽器自動在同源請求中攜帶。

缺點:

  • 容易受到 CSRF (跨站請求偽造) 的攻擊。因為瀏覽器會自動在請求中帶上 Cookie,攻擊者可以誘導用户點擊一個鏈接,從而以用户的身份發起惡意請求。
  • 需要額外的 CSRF 防護措施,如使用 Anti-CSRF Token、驗證 Origin/Referer Header 等。

結論: 是一個可行的方案,但必須配套完善的 CSRF 防禦機制。

選項三:內存(Memory)

將 Token 保存在 JavaScript 變量中。

let inMemoryToken = null;

// 登錄成功後
const login = async () => {
  const response = await loginAPI(username, password);
  inMemoryToken = response.data.token; // 存到內存變量
};

// 請求攔截器中添加
axios.interceptors.request.use((config) => {
  if (inMemoryToken) {
    config.headers.Authorization = `Bearer ${inMemoryToken}`;
  }
  return config;
});

// 退出登錄或頁面刷新時,Token 消失

優點:

  • 安全性極高:由於 Token 只存在於當前頁面的內存中,關閉頁面或刷新頁面後 Token 立即消失。XSS 攻擊者很難通過一次性注入的腳本持續地竊取到 Token(除非攻擊代碼常駐內存)。

缺點:

  • 體驗差:頁面一旦刷新,Token 就沒了,用户需要重新登錄。這對於單頁面應用 (SPA) 來説是致命的。

結論: 適用於安全要求極高、不介意頻繁登錄的場景(如銀行系統)。 對於普通 Web 應用,體驗不可接受。


終極方案:組合拳 + 架構思維

既然沒有完美的銀彈,現代前端的最佳實踐通常是 組合方案架構優化

實踐一:Cookie(HttpOnly + Secure) + 防禦 CSRF

這是最傳統但依然非常穩健的方案。

  1. 後端在登錄成功後,設置一個 HttpOnlySecure 的 Cookie 來存放 Token(可以是 JWT,也可以是 Session ID)。
  2. 前端基本不用操心 Token 的存儲和攜帶問題,由瀏覽器自動完成。
  3. 後端必須部署完善的 CSRF 防護策略,例如:
    • 從 Cookie 中讀取 Token 或 Session ID 進行身份驗證。
    • 同時,要求請求必須攜帶一個額外的(由後端生成並通過 API 返回給前端的)X-CSRF-Token Header,並與 Session 中存儲的值進行比對。

實踐二:Access Token + Refresh Token

這是目前 API 接口認證非常流行的方案,完美解決了內存存儲體驗差的問題。

  1. 登錄:用户輸入密碼登錄。
  2. 返回雙 Token:服務端返回兩個 Token:
    • access_token:短期有效(例如 2 小時),用於請求受保護的 API。
    • refresh_token:長期有效(例如 7 天),僅用於獲取新的 access_token,不應具備API訪問權限。
  3. 存儲策略
    • access_token存入內存。這樣即使被 XSS 竊取,有效期也很短,風險可控。
    • refresh_token存入 HttpOnly Cookie。因為它有效期長,必須嚴加保護。由於其本身不直接用於業務請求,即使遭遇 CSRF,攻擊者也無法用它來做任何關鍵操作(只能用來換一個短期的 access_token,而該 access_token 又會因為存在於內存而難以被攻擊者獲取)。
  4. 無感刷新:當 access_token 過期後,前端自動(通過 refresh_token)調用刷新接口獲取新的 access_token,用户無感知。

這個方案在安全性和用户體驗之間取得了絕佳的平衡,是當前眾多大型應用的首選。

總結與建議

ScreenShot_2026-01-14_093522_079

給你的最終建議:

  • 如果你在做的是一個簡單的、內部使用的、對安全性要求不高的工具,用 localStorage 圖個方便也無可厚非,但要清楚風險。
  • 如果你在做的是一個傳統的、服務端渲染的多頁應用,使用 HttpOnly Cookie 並配套 CSRF 防護是標準做法。
  • 如果你在做的是一個現代化的 SPA(如 React/Vue 應用),強烈推薦研究並採用 Access Token (內存) + Refresh Token (HttpOnly Cookie) 的方案。

安全沒有絕對,只有相對的權衡。理解每種方案的利弊,並根據你的實際業務場景做出最適合的選擇,才是最重要的。

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文檔,大家一起討論學習,一起進步。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.