搞懂 localStorage、sessionStorage、Cookie 三者差異是前端工程師面試的基本功。本文用簡單範例說明各自的用途、儲存限制與安全性重點,並延伸介紹 CSRF、SameSite 與 CSP 等網頁安全概念,助你一次掌握重點。
Written by: Chia1104 CC BY-NC-SA 4.0
今年不少時間在面試,其中最常被問到的就是這題,『幫我說明 localStorage、sessionStorage 跟 Cookie 的差異』,這裡也稍微說明一下,順便分享一個較 奇特 的面試經驗。
localStorage 可以想成「跟著網域走的長期置物櫃」,只要使用者或程式碼沒有主動清掉,它就會一直存著資料,即使重開瀏覽器、重新開機都還在。這些資料只會留在瀏覽器端,不會隨著每一次 HTTP 請求被送到伺服器,所以很適合拿來放一些「和後端無關、但要長期記住的設定」,例如:深色/淺色主題、側邊欄是否展開、列表排序偏好等等。
在容量上,localStorage 通常有數 MB 的空間,遠比 Cookie 動不動就只有幾 KB 來得寬裕,也用簡單的 key-value 介面操作,例如 localStorage.setItem('theme', 'dark')。缺點是:因為資料完全由前端控制,也不會自動過期,所以不適合丟敏感資訊(像是 access token 的原文內容),而且一不小心就會變成「永遠沒人打掃的儲物間」,忘了自己曾經塞過什麼進去。
如果說 localStorage 是「長期置物櫃」,那 sessionStorage 就比較像「這個分頁專用的暫存桌」。它跟 localStorage 一樣是存在瀏覽器、用 key-value 的方式儲存資料,也不會被自動帶到伺服器,但差別在於生命週期:只要該分頁或該視窗關掉,sessionStorage 裡的東西就會被清空,甚至在某些瀏覽器中,開一個新分頁也不會共享原本分頁的 sessionStorage。
這種特性非常適合拿來存「只跟這次操作流程有關的短期狀態」,例如:多步驟表單填寫進度、當前搜尋條件、某個臨時的 UI 狀態等。好處是:不用自己處理清理機制,使用者關掉分頁就自然消失;壞處就是,一旦使用者不小心關了分頁再打開,你也救不回來,只能重新來過。
Cookie 比較像「會被偷偷塞進每一趟 HTTP 請求裡的小紙條」,只要符合同一網域、路徑與安全條件,瀏覽器就會在發送請求時自動帶上對應的 Cookie 給伺服器。這也是為什麼 Cookie 一直是登入狀態、追蹤 ID、A/B 測試標記等「伺服器需要知道的資料」的主力工具:後端什麼都不用多做,收到請求就能從 Cookie 裡認出來「這是誰」。
Cookie 的容量通常只有幾 KB,而且因為每次請求都會被帶上去,多放一點資料就會變成白白耗網路流量、也拖慢請求。它可以透過 Expires 或 Max-Age 設定過期時間,不設定的話通常是關閉瀏覽器就失效的「session cookie」。現代瀏覽器也提供 HttpOnly、Secure、SameSite 等標記,讓 Cookie 在安全性和跨站行為上有更多限制與保護。
實務上,被問到這題時,可以用幾個維度快速做回答:
最後稍微分享一場面試的經驗,這裡就不說是哪家,只給個參考跟分享。
有一次在面試時也是被問到這題,那時候也是就上面這些特色做說明,當我最後講完 Cookie 時那個面試官就突然問說『所以 Cookie 可以設定 CSRF 嗎?』,其實當下我沒聽清楚,那時候還聽成 CSR (Client-Side Rendering) 但心裡想的卻是 CSP (Content Security Policy),當然那場面試結果可想而知...
但這裡就不針對 這狀況 多做說明,主要簡單講這三個的差異
嚴格來說,不是 在 Cookie 上設定 CSRF,而是「利用 Cookie 的 SameSite 屬性來幫忙防禦 CSRF」,再搭配傳統的 CSRF Token 等機制會比較安全。
CSRF 之所以成立,是因為瀏覽器會在跨站請求中,幫使用者自動夾帶 Cookie,伺服器看到合法的 Session Cookie,就以為是使用者本人發的請求。
所以 Cookie 本身是「問題的其中一個來源」,但同時也可以透過一些屬性設定,減少被濫用的機會,例如 SameSite。
在 Cookie 上加上 SameSite 屬性,可以控制「跨站請求時,要不要送出這顆 Cookie」:
SameSite=Strict:只有同站請求才會帶 Cookie,基本上可以擋掉大多數 CSRF,但 UX 可能會被影響。SameSite=Lax:頂層導覽的 GET 可能會帶 Cookie,但像跨站的表單 POST、圖片載入、隱藏請求就不會帶 Cookie,在安全性與使用性之間取得折衷。但通常這狀況會用 CSRF token 放在表單中做使用。
<input type="hidden" name="csrf-token" value="GENERATED_BY_SSR" />這個 CSRF Token 主要是透過後端渲染而來的,後端需要保存這 token,前端再發 POST 請求時需要攜帶這 token,以讓後端做驗證,來確保是該網站縮發的請求。
至於什麼是 CSR 這裡就不說了,因為毫無相關。
CSP 是一種瀏覽器層級的「白名單式」網站安全機制,用來限制網頁可以載入與執行哪些外部資源。它的主要目的是降低 XSS(跨站腳本)與各種注入攻擊的風險。
CSP 的理念是:預設一律不信任,只明確 允許 特定來源與類型的資源。 常見會被管控的資源包含 JavaScript、CSS、圖片、字型、iframe、Ajax 請求等。
CSP 通常透過 HTTP Response Header Content-Security-Policy(或 meta 標籤)來設定一組策略字串。
也可以先用 Content-Security-Policy-Report-Only 以 只回報不阻擋 模式上線,收集違規行為再逐步收緊。
常見 directive 如:
default-src:預設允許的來源,例如 default-src 'self' 表示只允許同來源所有資源。script-src、style-src、img-src:分別控制 JS、CSS、圖片的允許來源,例如只允許自家網域與特定 CDN。CSP 尤其對 XSS 很有幫助,因為就算攻擊者成功注入 <script>,瀏覽器也會因不在允許清單而阻擋執行。
它也能限制資料上報目標(例如 connect-src、form-action),減少資料外洩與惡意外連的風險。