
Cookie 屬性詳解:SameSite、Secure、HttpOnly 與 CHIPS
登入用的 Cookie 已在瀏覽器內儲存,但某個請求沒有帶上;嵌入式聊天工具在一個網站記得用戶,換到另一個網站卻重新開始。這些現象可能涉及不同規則,不能單靠加上更多屬性來解決。
Secure、HttpOnly、SameSite、Partitioned 和 __Host- 各自處理不同邊界。以下由 Cookie 的傳送方式開始,逐項說明它們如何配合 CSRF、XSS 和第三方 Cookie 防護,以及哪些問題仍要由伺服器處理。
日文原文發布: 2026-06-17
SameSite:減少跨網站風險,不能取代授權
SameSite 限制 Cookie 在跨網站請求中傳送。CSRF 攻擊會誘使已登入用戶的瀏覽器向目標網站發出非預期請求;SameSite 可以阻止部分情況,但不能判斷一項操作是否獲得授權。
如表格未能完整顯示,可左右捲動。
| 設定值 | 主要行為 | 應測試的情況 |
|---|---|---|
| Strict | 只限同網站情境。 | 從外部網站點擊普通連結時,第一個請求不會帶上 Cookie。 |
| Lax | 亦允許以 GET 等安全方法進行跨網站頂層導覽。 | 普通連結、重新導向,以及以 POST 返回的流程。 |
| None | 不設 SameSite 跨網站限制,但必須有 Secure。 | 瀏覽器政策及其他 Cookie 限制仍然適用。 |
明確設定 Lax 時,跨網站 iframe、fetch 和一般 POST 表單提交都不會帶上這個 Cookie。省略 SameSite 則未必相同:部分瀏覽器有相容處理,會讓剛設定的 Cookie 隨頂層 POST 請求傳送,例如設定後兩分鐘內。測試時不要將省略與明確設定 Lax 視為同一情況。
None 不能解除第三方 Cookie 封鎖。若網站用 GET 更改資料,Lax 允許的導覽仍可能觸發操作;不可信任的同網站子網域,也可能發出符合 SameSite 條件的請求。
應按應用程式需要加入 CSRF token、Origin 或 Referer 驗證、Fetch Metadata 標頭檢查及重新驗證身份。這些伺服器端防護不能一概由 SameSite 取代。
網站(site)不等於來源(origin)
來源(origin)由網址的 scheme(例如 https)、主機和連接埠組成。包含 scheme 的網站判定(schemeful site)則以 scheme 和可註冊網域為基礎。以下比較一般頂層文件的網址:
如表格未能完整顯示,可左右捲動。
| 網址組合 | 來源(origin) | 網站(site) |
|---|---|---|
| https://app.example.com 與 https://api.example.com | 不同來源 | 同網站 |
| https://example.com 與 http://example.com | 不同來源 | scheme 不同,屬於不同網站 |
iframe 的祖先文件也會影響同網站情境的判定,因此不能只比較兩個主機名稱。連接埠不同代表不同來源,但 Cookie 本身不按連接埠隔離。
Cookie 會否傳送、CORS 會否容許讀取跨來源回應,以及 JavaScript 能否存取另一份文件的 DOM,是不同問題。帶憑證的 CORS 回應需要以 Access-Control-Allow-Origin 指定請求來源,而非萬用字元,並設定 Access-Control-Allow-Credentials: true。讀取回應被 CORS 拒絕,不代表請求沒有送出或沒有被伺服器處理。
Partitioned 與 CHIPS:按頂層網站分開狀態
CHIPS 的全名是 Cookies Having Independent Partitioned State。Partitioned 屬性在 Cookie 儲存時加入頂層網站分區,同時保留 Cookie 原有的主機或網域範圍;分區鍵中的網站亦包含 scheme。
Set-Cookie: __Host-chat=value; Secure; Path=/; SameSite=None; Partitioned
Partitioned 必須配合 Secure。這個跨網站嵌入例子還使用 SameSite=None,因為分區儲存不會取消 SameSite 的限制。
假設 support.chat.example 嵌入 retail.example 時設定了 Cookie,該 Cookie 便屬於 retail.example 的頂層網站分區。同一服務嵌入 news.example 時,不會收到 retail.example 分區的 Cookie;返回 retail.example 則可繼續使用原來的獨立狀態。
嵌入式聊天、地圖或其他元件,可利用這個機制按網站維持狀態。它不是讓無關網站共用同一登入狀態的方案。不支援 Partitioned 的環境可能忽略該屬性;若其他政策容許,Cookie 可能被當作普通未分區 Cookie。應在目標瀏覽器驗證,不能認定寫入屬性便必然做到隔離。
改用 localStorage,不會自動消除保安風險
localStorage 的值可由 JavaScript 讀取。如果攻擊者能在應用程式的來源中執行指令碼,便可能直接竊取其中的 access token。
HttpOnly Cookie 雖然阻止直接讀取,但符合條件的請求仍會帶上它,CSRF 和 XSS 借用登入身份發出的請求仍須防範。兩種儲存方式面對的攻擊面不同,不能只問哪一種「永遠比較安全」。
會話設計須一併考慮 token 有效期、輪替、登出、伺服器端撤銷、重新驗證身份和權限檢查。儲存位置只是其中一環。
按實際登入或嵌入流程選擇屬性
供伺服器使用、限定於單一主機的登入會話,可以由以下形式開始評估:
Set-Cookie: __Host-session=...; Path=/; Secure; HttpOnly; SameSite=Lax
用了外部身份提供者(IdP)或付款服務,不代表一定要選 None。先看返回網站時是頂層 GET、POST 回傳,還是 iframe,再判斷 Strict、Lax 或 None 是否合適。
如果嵌入式小工具需要由自己的 JavaScript 讀取狀態,並按頂層網站分開儲存,可考慮:
Set-Cookie: __Host-widget=...; Path=/; Secure; SameSite=None; Partitioned
小工具例子刻意沒有 HttpOnly,因為該例需要指令碼存取。若是只供伺服器使用的會話值,便應加入 HttpOnly。省略號只是佔位值,實作時須換成合適的 session ID 或其他狀態值。
這些標頭只示範屬性組合,並非完整的身份驗證系統。仍要檢查瀏覽器支援、Cookie 封鎖、CORS、iframe 限制、Storage Access API 的整合,以及伺服器的授權規則。
參考資料及來源
編輯說明
本文使用 AI 協助編輯,並在發布前由編輯核對。內容仍可能包含事實、理解或時效上的錯誤;作出重要決定前,請查閱所列的一手資料或官方文件。

