SameSite Cookie 食譜

ChromeFirefoxEdge 和其他機構為了配合 IETF 提案而變更預設行為,因此改善了更優異的 Cookie,因此:

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

建議您更新第三方 Cookie 的屬性,以免日後遭到封鎖。

瀏覽器支援

  • 51
  • 16
  • 60
  • 13

來源

跨網站或第三方 Cookie 的用途

在許多常見用途和模式中,Cookie 都必須傳送至第三方環境。如果您提供或依賴上述其中一種用途,請務必由您或提供者更新 Cookie,確保服務正常運作。

<iframe>中的內容

<iframe> 中顯示的其他網站內容,是來自第三方內容。標準用途包括:

  • 其他網站共用的嵌入內容,例如影片、地圖、程式碼範例和社群貼文。
  • 來自外部服務的小工具,例如付款、日曆、預訂和預訂功能。
  • 社交按鈕或反詐欺服務等小工具,會建立較不明顯的 <iframes>

這裡使用 Cookie 來執行其他工作,包括維持工作階段狀態、儲存一般偏好設定、啟用統計資料,或是為現有帳戶的使用者提供個人化內容。

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

由於網頁本身是可組合的,因此 <iframes> 也可用於嵌入在頂層或第一方情境中瀏覽的內容。iframe 使用的網站中顯示的任何 Cookie 都視為第三方 Cookie。如果您打算建立要嵌入其他網站的網站,且需要使用 Cookie 來讓這些網站正常運作,則您也必須將那些網站標示為可跨網站使用,或者可以在沒有網站的情況下流暢地改回使用。

網站的「不安全」要求

「不安全」這可能聽起來很令人擔心,但是指任何可能想要變更狀態的要求。在網路上,主要是 POST 要求標示為 SameSite=Lax 的 Cookie 會透過安全的頂層導覽傳送,例如點選連結即可前往其他網站。不過,使用 POST 向其他網站提交 <form> 時,就不會包含 Cookie。

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

此模式可用於網站,若網站能在傳回前將使用者重新導向至遠端服務,以便執行特定作業,例如重新導向至第三方識別資訊提供者。在使用者離開網站前,系統會設定一個 Cookie,其中包含單一使用權杖,且預期可在傳回要求上檢查此權杖,以減輕跨網站要求偽造 (CSRF) 攻擊。如果傳回的要求是透過 POST 傳送,您必須將 Cookie 標示為 SameSite=None; Secure

遠端資源

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

這也適用於使用 fetchXMLHttpRequest 從 JavaScript 傳出的要求。如果使用 credentials: 'include' 選項呼叫 fetch(),這些要求可能會包含 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。

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

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 會在網路上隨處使用,而且任何開發團隊很少具備完整瞭解網站組位置與用途的資訊,尤其是在跨網站使用的情況下。發生問題時,我們可能是第一次有人遇到這些問題,因此歡迎隨時與我們聯絡: