Cookies vs localStorage vs sessionStorage:選擇客戶端儲存方案
在建立網頁應用程式時,你經常需要在客戶端儲存資料——無論是使用者的主題偏好、購物車,還是身分驗證權杖。三個主要選項是 cookies、localStorage 和 sessionStorage。每個都有不同的特性,適合不同的情境。選錯可能導致安全漏洞、效能問題或糟糕的使用者體驗。
本文將剖析這些差異,提供實用指引,並幫助你決定下一個專案該使用哪種儲存機制。
快速比較
在深入細節之前,以下是三種儲存類型的高層次概覽:
| 功能 | Cookies | localStorage | sessionStorage |
|---|---|---|---|
| 容量 | 每個網域約 4KB | 每個來源約 5-10MB | 每個來源約 5-10MB |
| 持久性 | 可設定到期時間 | 直到明確清除 | 直到分頁/視窗關閉 |
| 傳送至伺服器 | 每次 HTTP 請求自動傳送 | 否 | 否 |
| 可透過 JavaScript 存取 | 是(除非設定 HttpOnly) | 是 | 是 |
| 範圍 | 網域與路徑 | 來源(協定 + 網域 + 連接埠) | 來源 + 分頁/視窗 |
| 易受 XSS 攻擊 | 是(若未設定 HttpOnly) | 是 | 是 |
| 易受 CSRF 攻擊 | 是(若用於身分驗證) | 否 | 否 |
Cookies:最早的客戶端儲存
Cookies 自網路早期就已存在。它們是小型資料片段(最大約 4KB),由瀏覽器儲存,並在每次對同一網域的 HTTP 請求中自動傳送給伺服器。
何時使用 Cookies
- 身分驗證工作階段:儲存伺服器每次請求需要驗證的工作階段 ID 或權杖。使用
HttpOnly、Secure和SameSite標記來降低 XSS 和 CSRF 風險。 - 伺服器端個人化:當伺服器必須在渲染頁面之前知道使用者偏好(例如語言、主題)時。
- 追蹤與分析:若設定得當,cookies 可以跨工作階段持續存在,並跨子網域共用。
安全性考量
Cookies 會自動傳送,這使得它們在未增加保護的情況下若用於身分驗證,容易受到 CSRF 攻擊。請務必設定 SameSite 屬性(Lax 或 Strict),並考慮使用 CSRF 權杖。對於敏感資料,使用 HttpOnly 防止 JavaScript 存取,以減少 XSS 影響。
在 HTTP 回應中設定安全 cookie 的範例:
Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600
localStorage:持久的鍵值儲存
localStorage 提供簡單的鍵值儲存,即使瀏覽器關閉後仍會保留。資料按來源(協定 + 網域 + 連接埠)儲存,不會自動傳送給伺服器。它非常適合儲存應在頁面重新整理和瀏覽器重新啟動後仍存在的非敏感資料。
何時使用 localStorage
- 使用者偏好:主題(深色/淺色)、字型大小、語言或版面設定。
- 快取:儲存 API 回應或靜態資料,以減少網路請求並改善離線體驗。
- 客戶端狀態:購物車內容、草稿表單資料或功能旗標。
安全性考量
localStorage 可透過 JavaScript 存取,因此任何 XSS 漏洞都可能暴露所有儲存的資料。除非你有強大的 XSS 防護,否則絕不要儲存密碼、個人識別碼或身分驗證權杖等敏感資訊。如果必須儲存權杖,請考慮改用 HttpOnly cookie 方式。
使用 localStorage 的範例:
// Save user preference
localStorage.setItem('theme', 'dark');
// Retrieve preference
const theme = localStorage.getItem('theme');
// Remove item
localStorage.removeItem('theme');
sessionStorage:每個分頁的儲存
sessionStorage 與 localStorage 類似,但生命週期較短:當分頁或視窗關閉時,資料會被清除。它的範圍限於單一分頁,因此資料不會在分頁或視窗之間共用,即使來源相同也一樣。
何時使用 sessionStorage
- 多步驟表單:在使用者逐步填寫時暫時儲存表單資料,完成後不保留。
- 單一分頁狀態:不應在分頁之間洩漏的資料,例如暫時的身分驗證狀態或一次性權杖。
- 敏感操作:當你希望使用者關閉分頁時自動清除資料,以減少暴露。
安全性考量
與 localStorage 一樣,sessionStorage 容易受到 XSS 攻擊。然而,其有限的生命週期和每個分頁的範圍縮小了攻擊者的機會窗口。儘管如此,仍應避免儲存高度敏感的資料。
使用 sessionStorage 的範例:
// Save form data
sessionStorage.setItem('formStep1', JSON.stringify({name: 'John'}));
// Retrieve form data
const step1 = JSON.parse(sessionStorage.getItem('formStep1'));
如何選擇:決策指南
使用以下有序清單來引導你的決策:
- 伺服器是否需要在每次請求時讀取資料?如果是,使用 cookies。例如:工作階段 ID。
- 資料是否需要跨瀏覽器工作階段持續存在?如果是,使用 localStorage。例如:使用者偏好。
- 資料是否應限於單一分頁?如果是,使用 sessionStorage。例如:多步驟表單資料。
- 資料是否敏感?避免儲存在 localStorage 或 sessionStorage 中。權杖請使用 HttpOnly cookies,且絕不要儲存密碼。
- 資料是否很大?Cookies 限制約 4KB;localStorage 和 sessionStorage 提供更大的容量。
安全性最佳實務
- 始終驗證並清理輸入以防止 XSS,XSS 可能危及任何客戶端儲存。
- 對身分驗證權杖使用 HttpOnly、Secure 和 SameSite cookies以降低 XSS 和 CSRF 風險。
- 避免在 localStorage 或 sessionStorage 中儲存敏感資料。如果必須,請加密並使用短到期時間。
- 實作內容安全政策(CSP)以降低 XSS 風險。
- 定期清除過時資料以避免達到儲存限制並減少暴露。
常見問題
我可以使用 localStorage 儲存身分驗證權杖嗎?
不建議,因為 localStorage 可透過 JavaScript 存取,使權杖容易受到 XSS 攻擊。最好使用帶有 Secure 和 SameSite 標記的 HttpOnly cookies。
當我複製分頁時,sessionStorage 會發生什麼事?
當你複製分頁時,新分頁會在複製當下取得原始分頁 sessionStorage 的副本。之後,它們就是獨立的。
Cookies 會在每次請求時傳送給伺服器嗎?
是的,目前網域的 cookies 會自動包含在每次 HTTP 請求中,如果你儲存太多資料,可能會影響效能。請謹慎使用。
需要快速格式化或驗證你儲存的 JSON 資料嗎?試試我們的 JSON Formatter,在將 JSON 負載儲存到客戶端儲存之前美化並除錯它們。