Chrome、 Firefox、 Edge 等瀏覽器正根據 IETF 提案「Incrementally Better Cookies」 變更預設行為, 以便:
- 沒有
SameSite屬性的 Cookie 會視為SameSite=Lax, 也就是說,預設行為是將 Cookie 限制在「僅限」第一方情境。 - 跨網站使用的 Cookie 必須指定
SameSite=None; Secure,才能納入第三方內容。
如果尚未更新第三方 Cookie 的屬性,請務必更新,以免日後遭到封鎖。
Browser Support
跨網站或第三方 Cookie 的用途
在許多常見的使用情況和模式中,都需要在第三方環境中傳送 Cookie。如果您提供或依賴其中一種使用情況,請確保您或供應商更新 Cookie,讓服務正常運作。
<iframe> 內的內容
在 <iframe> 中顯示其他網站的內容時,會處於第三方脈絡。標準用途包括:
- 從其他網站分享的嵌入內容,例如影片、地圖、程式碼範例和社群媒體貼文。
- 外部服務的小工具,例如付款、日曆、預訂和預約功能。
- 社群媒體按鈕或反詐欺服務等小工具,這些小工具會建立較不明顯的
<iframes>。
Cookie 可能會用於維護工作階段狀態、儲存一般偏好設定、啟用統計資料,或為現有帳戶使用者提供個人化內容。
由於網頁本質上是可組合的,<iframes>也用於嵌入頂層或第一方環境中檢視的內容。iframe 中顯示的網站使用的任何 Cookie 都視為第三方 Cookie。如果您要建立可供其他網站嵌入的網站,且需要 Cookie 才能運作,也必須確保這些 Cookie 已標示為可跨網站使用,或確保沒有這些 Cookie 也能正常運作。
跨網站的「不安全」要求
「不安全」聽起來可能令人擔憂,但這裡是指任何可能用於變更狀態的要求。在網路上,這主要是指 POST 要求。標示為 SameSite=Lax 的 Cookie 會在安全的頂層導覽中傳送,例如點選連結前往其他網站。不過,如果使用 POST 將 <form> 提交至其他網站,就不會包含 Cookie。
這個模式適用於可將使用者重新導向至遠端服務,執行某些作業後再返回的網站,例如重新導向至第三方身分識別提供者。使用者離開網站前,系統會設定含有單次使用權杖的 Cookie,預期在返回要求時檢查這個權杖,以防範跨網站要求偽造 (CSRF) 攻擊。如果返回要求是透過 POST 傳送,您需要將 Cookie 標示為 SameSite=None; Secure。
遠端資源
網頁上的任何遠端資源 (例如來自 <img> 標記或 <script> 標記) 可能會依附於隨請求傳送的 Cookie。常見用途包括追蹤像素和個人化內容。
如果您使用 fetch 或 XMLHttpRequest 從 JavaScript 傳送要求,也適用這項規定。如果使用 credentials: 'include' 選項呼叫 fetch(),這些要求可能會包含 Cookie。對於 XMLHttpRequest,預期 Cookie 通常會以 withCredentials 值表示,適用於 true。這些 Cookie 必須適當標示,才能納入跨網站要求。
WebView 中的內容
平台專屬應用程式中的 WebView 由瀏覽器提供支援。開發人員必須測試影響應用程式的限制或問題是否也適用於應用程式的 WebView。
Android 也允許平台專屬應用程式使用 CookieManager API 直接設定 Cookie。
與使用標頭或 JavaScript 設定的 Cookie 相同,如果 Cookie 預定用於跨網站,請考慮加入 SameSite=None; Secure。
如何導入 SameSite
視需求將僅限在第一方情境中使用的 Cookie 標示為 SameSite=Lax 或 SameSite=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 的位置,尤其是在跨網站用途中。遇到問題時,您可能是第一個遇到問題的人,因此請不吝與我們聯絡:
- 在 GitHub 上的
SameSite範例存放區中提出問題。 - 在 StackOverflow 的「samesite」標記中提問。
- 如果 Chromium 的行為有問題,請在 Chromium 問題追蹤工具中提出錯誤。
- 如要瞭解 Chrome 的進度,請前往
SameSite更新頁面。