在瀏覽器開發者工具檢視 Cookie 時,經常會看見 Expires / Max-Age 欄位顯示為「Cookie Expires Session」。想了解相關基礎細節與原理,可前往 CSRF 跨站請求偽造攻擊原理與 Anti-CSRF Token 防禦實作 觀看。本篇則專注於探討當 Cookie 的 Expires 顯示為 Session 時的背後成因,以及如何在前端與後端程式碼中正確指定過期時間。
為什麼 Cookie 的 Expires 會顯示為 Session?
在檢視網頁應用程式的 Cookie 狀態時,開發者工具(如 Chrome DevTools 的 Application 分頁)中的 Expires / Max-Age 欄位若顯示為 Session,代表這個 Cookie 被定義為「工作階段 Cookie (Session Cookie)」。
這並不是系統發生錯誤,而是因為該 Cookie 在建立時,沒有明確指定 Expires 或 Max-Age 屬性。根據 HTTP 規範,當未設定明確的存活時間時,瀏覽器會將其視為暫存資料。
| 屬性狀態 | 瀏覽器行為 | 生命週期長度 |
|---|---|---|
| 未設定 Expires / Max-Age (顯示 Session) | 僅存在於當前瀏覽器分頁或視窗的記憶體中 | 當關閉該瀏覽器分頁或視窗時自動銷毀 |
| 設定明確的 Expires 日期 | 寫入硬碟或永久快取儲存 | 直到指定的絕對時間點到達才過期 |
| 設定明確的 Max-Age 秒數 | 寫入硬碟或永久快取儲存 | 從當下開始計算,經過指定的相對秒數後過期 |
Session Cookie 的特性與影響
當 Cookie 顯示為 Session 時,其生命週期完全綁定於使用者的瀏覽行程(Session)。
- 生命週期短暫:一旦使用者關閉了當前的瀏覽器分頁、視窗,或者結束瀏覽器行程,該 Cookie 就會被瀏覽器自動刪除。
- 無法跨瀏覽器重啟保留:如果使用者需要「記住我」或長時間維持登入狀態,使用 Session Cookie 就無法達成需求,因為重新開機或重啟瀏覽器後,狀態就會遺失。
如何在程式碼中設定 Expires 或 Max-Age
要避免 Cookie 變成 Session Cookie,讓態在瀏覽器關閉後依然能依指定時間保存,必須在建立 Cookie 時透過 Expires 或 Max-Age 明確給定有效期限。
1. 前端 JavaScript 設定範例
如果是在前端透過 document.cookie 寫入 Cookie,必須手動帶入符合 GMT 格式的日期字串(使用 Expires),或是指定相對秒數(使用 Max-Age):
// 使用 Expires 設定絕對過期時間(需轉換為 UTC/GMT 格式字串)
const expireDate = new Date();
expireDate.setTime(expireDate.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 天後
document.cookie = `user_token=abc123xyz; expires=${expireDate.toUTCString()}; path=/`;
// 或者使用 Max-Age 設定相對秒數(單位為秒,例如 7 天 = 604800 秒)
document.cookie = "user_token=abc123xyz; max-age=604800; path=/";
2. 後端伺服器 Set-Cookie 設定範例
在實際的商業邏輯中,為了安全性(例如加上 HttpOnly 防止 XSS 攻擊),通常 Cookie 是由後端伺服器透過 Set-Cookie 回應標頭來寫入。以下為常見的 Node.js / Express 寫法:
// 後端透過 Set-Cookie 標頭回傳明確的過期時間
res.cookie('session_id', 'xyz789abc', {
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 天(以毫秒為單位)
httpOnly: true, // 提高安全性,禁止前端 JS 讀取
secure: true, // 僅允許 HTTPS 傳輸
sameSite: 'Strict' // 跨站防禦設定
});
只要在伺服器端或前端寫入時加上了上述的時間參數,重新整理瀏覽器開發者工具,原本的 Session 字樣就會替換為具體的過期時間或剩餘秒數。
⚠️ 實務開發注意事項與常見踩坑排查
在實際企業級開發與瀏覽器環境中,針對 Cookie 的生命週期與作用範圍,經常會遇到以下 2 個極易踩雷的技術盲點與邊界條件:
1. 瀏覽器分頁還原功能(Session Restore)對 Session Cookie 的影響
- 踩坑情境與觸發原因:許多開發者誤以為「關閉瀏覽器分頁」才會讓 Session Cookie 失效。但在現代 Chrome 等瀏覽器的「啟動時繼續上次分頁 (Continue where you left off)」或分頁群組還原機制下,重啟瀏覽器時往往會自動復原先前的分頁與記憶體狀態,導致開發者誤以為未設定過期時間的 Cookie 具有永久保存特性,因而造成登入狀態異常混亂。
- 實務防呆與排錯解法:若業務邏輯要求「關閉瀏覽器必須強制登出」,絕對不能依賴未設定過期時間的預設 Session Cookie,而必須在後端配合明確的
session管理機制,或是明確設定較短的Max-Age。
2. Cookie 作用域(Path 與 Domain)未對齊導致設定無效或覆寫
- 踩坑情境與觸發原因:當開發者在程式碼中寫了
document.cookie設定了Max-Age,卻發現開發者工具裡的Expires依然顯示為Session,或者重新整理後 Cookie 沒有更新。這通常是因為寫入時缺少了正確的path=/,導致瀏覽器在當前子路徑下建立了一個新的 Cookie,而原本根目錄的 Session Cookie 依然存在。 - 實務防呆與排錯解法:在前後端設定 Cookie 時,若未明確指定
path或domain,瀏覽器會以預設的當前請求路徑建立。建議在寫入時務必明確帶入path=/與正確的網域範圍,避免多個同名 Cookie 在不同路徑下互相干擾。
常見問題 (FAQ)
Q1:Cookie 顯示為 Session 時,關閉瀏覽器分頁就會立刻失效嗎?
- 解答:Session Cookie 何時消失、關閉分頁或瀏覽器後為什麼可能還在,可前往〈Session Restore 是什麼?瀏覽器還原分頁時 Session Cookie 為什麼沒消失〉觀看。
Q2:為什麼已經在前端寫了 Max-Age,F12 檢查還是顯示 Session?
- 解答:這通常是因為寫入 Cookie 時漏掉了
path=/參數,或者寫入時指定的路徑與當前檢視的路徑不符。如果沒有明確指定作用域路徑,瀏覽器會將 Cookie 建立在當前的子路徑下,導致原本根目錄或其他路徑下的 Cookie 沒有被覆寫,或者前端讀寫對應錯誤。建議寫入時務必加上path=/。
Q3:伺服器端設定 Cookie 時,maxAge 單位應該用毫秒還是秒?
- 解答:這取決於您使用的後端框架與函式庫。以 Node.js 的 Express 框架(
res.cookie)來說,maxAge參數接收的是毫秒 (Milliseconds);但在標準 HTTP 標頭的Set-Cookie規範中,Max-Age接收的則是秒 (Seconds)。開發時務必看清楚框架的文件說明,否則容易把 7 天設定成僅僅 7 毫秒而瞬間過期。
Q4:Session Cookie 與 sessionStorage 有什麼不同?
- 解答:雖然兩者名稱都有 Session 且同樣會在關閉瀏覽器時清除,但
sessionStorage是 HTML5 Web Storage API 的一部分,僅存在前端且容量較大(約 5MB),不會隨著 HTTP 請求發送到後端伺服器;而 Cookie(包含 Session Cookie)體積較小(約 4KB),但每次瀏覽器發出 HTTP 請求時,都會自動帶在Cookie標頭中傳遞給後端。
發佈留言