SameSite Cookie 食譜

ChromeFirefoxEdge 和其他網站正配合 IETF 提案變更預設行為,漸進改善 Cookie,藉此達成下列目標:

  • 系統會將沒有 SameSite 屬性的 Cookie 視為 SameSite=Lax,也就是說,預設行為是將 Cookie「只限」用於第一方內容。
  • 跨網站使用 Cookie 必須指定 SameSite=None; Secure,才能納入第三方內容。

如果您還沒這麼做,請更新第三方 Cookie 的屬性,以免日後封鎖這些 Cookie。

瀏覽器支援

  • Chrome:51.
  • Edge:16.
  • Firefox:60。
  • Safari:13。

資料來源

跨網站或第三方 Cookie 的用途

有許多常見用途和模式需要在第三方情境中傳送 Cookie。如果您提供或依賴其中一個用途,請確保您或供應商已更新其 Cookie,以確保服務正常運作。

<iframe>中的內容

<iframe> 中顯示的不同網站內容屬於第三方內容。標準用途包括:

  • 從其他網站分享的嵌入內容,例如影片、地圖、程式碼範例和社群媒體貼文。
  • 來自外部服務的資訊方塊,例如付款、日曆、預訂和預約功能。
  • 小工具 (例如社群媒體按鈕或防詐欺服務),這些小工具會產生較不明顯的<iframes>

這類 Cookie 可用於維持工作階段狀態、儲存一般偏好設定、啟用統計資料,或為已註冊帳戶的使用者提供個人化內容。

在瀏覽器視窗中嵌入內容與網頁網址不符的圖表。
如果嵌入內容來自不同於頂層瀏覽情境的網站,則為第三方內容。

由於網頁本質上是可組合的,<iframes> 也用於在頂層或第一方情境中嵌入內容。在 iframe 中顯示的網站使用任何 Cookie 都會視為第三方 Cookie。如果您要建立其他網站可嵌入的網站,且需要 Cookie 才能正常運作,也請務必將這些網站標示為跨網站使用,或在沒有 Cookie 的情況下,能順利回復。

跨網站的「不安全」要求

「不安全」聽起來可能有點疑慮,但是指任何意圖變更狀態的要求。在網路上,這通常是指 POST 要求。標示為 SameSite=Lax 的 Cookie 會在安全的頂層導覽 (例如點按連結前往其他網站) 時傳送。不過,使用 POST 將 <form> 提交至其他網站的操作不會包含 Cookie。

圖表:要求從一個網頁移動到另一個網頁。
如果傳入的要求使用「安全」方法,頁面會傳送 Cookie。

此模式適用於可將使用者重新導向至遠端服務的網站,以便在返回前執行某些作業,例如重新導向至第三方身分識別資訊提供者。在使用者離開網站前,系統會設定內含單一使用憑證的 Cookie,並預期此權杖可在傳回要求上檢查,以緩解跨網站要求偽造 (CSRF) 攻擊。如果該傳回要求是透過 POST 傳送,您必須將 Cookie 標示為 SameSite=None; Secure

遠端資源

網頁上的任何遠端資源 (例如 <img> 標記或 <script> 標記) 都可能會依賴透過請求傳送的 Cookie。常見用途包括追蹤像素和個人化內容。

這項規定也適用於使用 fetchXMLHttpRequest 從 JavaScript 傳送的要求。如果 fetch() 是使用 credentials: 'include' 選項 呼叫,這些要求可能會包含 Cookie。對於 XMLHttpRequest,預期 Cookie 通常會透過 truewithCredentials表示。這些 Cookie 必須標示為適當,才能納入跨網站要求。

WebView 中的內容

特定平台應用程式中的 WebView 是由瀏覽器提供動力。開發人員需要測試影響應用程式的限制或問題是否也適用於應用程式的 WebView。

Android 也允許其平台專屬應用程式使用 CookieManager API 直接設定 Cookie。如同使用標頭或 JavaScript 設定 Cookie,如果 Cookie 是用於跨網站使用,建議您加入 SameSite=None; Secure

立即導入 SameSite 的方法

視需求將任何僅在第一方情境中需要的 Cookie 標示為 SameSite=LaxSameSite=Strict。如果您未標記這些 Cookie,而是依賴預設瀏覽器行為來處理,這些 Cookie 在不同瀏覽器中的行為可能會不一致,並可能會為每個 Cookie 觸發控制台警告。

Set-Cookie: first_party_var=value; SameSite=Lax

請務必將第三方情境中所需的所有 Cookie 標示為 SameSite=None; Secure。這兩項屬性皆為必要屬性。如果您只指定 None,而未指定 Secure,系統會拒絕 Cookie。為了說明瀏覽器實作方式的差異,您可能需要使用「處理不相容的用戶端」中所述的一些緩解策略。

Set-Cookie: third_party_var=value; SameSite=None; Secure

處理不相容的用戶端

由於這些變更 (包括 None 和更新預設行為) 仍屬於新功能,因此不同瀏覽器會以不同方式處理這些變更。如要查看已知問題的清單,請參閱 chromium.org 的更新頁面,但這份清單可能不完整。

其中一個可行的解決方法是同時以新樣式和舊樣式設定每個 Cookie:

Set-cookie: 3pcookie=value; SameSite=None; Secure
Set-cookie: 3pcookie-legacy=value; Secure

實作較新行為的瀏覽器會使用 SameSite 值設定 Cookie。沒有實作新行為的瀏覽器會忽略該值,並設定 3pcookie-legacy Cookie。處理所包含的 Cookie 時,您的網站應先檢查是否有新款 Cookie,如果找不到,則改用舊款 Cookie。

以下範例說明如何在 Node.js 中使用 Express 架構及其 cookie-parser 中介層執行此操作:

const express = require('express');
const cp = require('cookie-parser');
const app = express();
app.use(cp());

app.get('/set', (req, res) => {
  // Set the new style cookie
  res.cookie('3pcookie', 'value', { sameSite: 'none', secure: true });
  // And set the same value in the legacy cookie
  res.cookie('3pcookie-legacy', 'value', { secure: true });
  res.end();
});

app.get('/', (req, res) => {
  let cookieVal = null;

  if (req.cookies['3pcookie']) {
    // check the new style cookie first
    cookieVal = req.cookies['3pcookie'];
  } else if (req.cookies['3pcookie-legacy']) {
    // otherwise fall back to the legacy cookie
    cookieVal = req.cookies['3pcookie-legacy'];
  }

  res.end();
});

app.listen(process.env.PORT);

這種做法需要您額外設定備用 Cookie,並在設定和讀取 Cookie 時進行變更。不過,無論瀏覽器行為為何,這項功能都應涵蓋所有瀏覽器,並讓第三方 Cookie 正常運作。

您也可以在傳送 Set-Cookie 標頭時,使用使用者代理程式字串偵測用戶端。請參閱不相容用戶端的清單,並使用適合您平台的使用者代理程式偵測程式庫,例如 Node.js 上的 ua-parser-js 程式庫。這種做法僅要求您做出一項變更,但使用者代理程式監聽功能可能無法擷取到所有受影響的使用者。

支援語言、程式庫和架構的 SameSite=None

大多數語言和程式庫都支援 Cookie 的 SameSite 屬性。不過,由於 SameSite=None 的新增功能仍屬於較新的功能,因此您可能需要針對某些標準行為進行調整。這些行為已記錄在 GitHub 上的 SameSite 範例存放區中。

取得說明

網站上到處都會使用 Cookie,但開發團隊很少能完全瞭解網站在何處設定及使用 Cookie,特別是在跨網站使用 Cookie 的情況下。當您遇到問題時,可能是第一次遇到這種問題,因此歡迎隨時與我們聯絡: