网络正在逐步告别第三方Cookie,这项曾经被广泛依赖的技术正在走向终结。Cookie最初在1994年由网景公司引入,用于支持虚拟购物车等功能,长期以来一直是网络功能的基础。然而,出于隐私和安全考虑,业界正在努力彻底淘汰它们。
各大浏览器(Chrome、Safari、Firefox和Edge)都在逐步淘汰第三方Cookie,尽管这个过程是渐进的。虽然这一变化增强了用户隐私,但也破坏了依赖第三方Cookie的合法功能,比如单点登录(SSO)、欺诈防护和嵌入式服务。
为什么Cookie检测仍然重要
理想情况下,我们应该完全放弃第三方Cookie,尽快使用隐私优先的替代方案重新设计集成。但现实中,这种迁移可能需要数月甚至数年时间,特别是对于遗留系统或第三方供应商。与此同时,用户已经在使用禁用第三方Cookie的浏览器,但往往不知道有功能缺失。
想象一个旅行预订平台,它嵌入一个来自第三方合作伙伴的iframe来显示实时火车或航班时刻表。这个嵌入式服务使用自己域名上的Cookie来验证用户身份并个性化内容,比如显示保存的行程或会员奖励。但当浏览器阻止第三方Cookie时,iframe无法访问这些数据,用户看到的不是流畅的体验,而是错误页面、空白屏幕或无效的登录提示。
检测第三方Cookie阻止不仅是良好的技术实践,更是用户体验的前线防御。
为什么检测第三方Cookie阻止如此困难
检测第三方Cookie是否被支持并不像调用navigator.cookieEnabled
那么简单。即使是这样看似安全的检查,也无法告诉你真正需要知道的信息:
// 这样做无法检测第三方Cookie阻止
function areCookiesEnabled() {
if (navigator.cookieEnabled === false) {
return false;
}
try {
document.cookie = "test_cookie=1; SameSite=None; Secure";
const hasCookie = document.cookie.includes("test_cookie=1");
document.cookie = "test_cookie=; Max-Age=0; SameSite=None; Secure";
return hasCookie;
} catch (e) {
return false;
}
}
这个函数只能确认Cookie在当前(第一方)上下文中有效,对于第三方场景(比如另一个域名上的iframe)却一无所知。更糟糕的是,它具有误导性:在某些浏览器中,即使Cookie被阻止,navigator.cookieEnabled
在第三方iframe中仍可能返回true
。
现代浏览器如何处理第三方Cookie
Safari:完全阻止第三方Cookie
自版本13.1起,Safari默认阻止所有第三方Cookie,没有例外,即使用户之前与嵌入域有过交互。对于需要Cookie访问的嵌入内容(如SSO iframe),Safari提供了存储访问API,需要用户手势才能授予存储权限。
Firefox:按设计分区Cookie
Firefox的总Cookie保护按站点隔离Cookie。第三方Cookie仍然可以设置和读取,但按顶级站点分区,这意味着同一第三方在不同站点上的Cookie是分开存储的,无法共享。
Chrome:从弃用计划到隐私沙盒
基于Chromium的浏览器默认仍允许第三方Cookie,但情况正在改变。从Chrome 80开始,第三方Cookie必须显式标记为SameSite=None; Secure
,否则会被拒绝。
Google原计划在2022年淘汰第三方Cookie,但时间表多次更新。2024年7月,Google明确表示没有计划单方面弃用第三方Cookie,而是转向用户选择界面,让用户决定是否全局阻止或允许第三方Cookie。
Edge:基于追踪器的阻止
Edge(基于Chromium)与Chrome共享对第三方Cookie的处理方式,并引入了追踪预防模式:基本、平衡(默认)和严格。在平衡模式下,它会阻止已知的第三方追踪器,但允许许多未被归类为追踪器的第三方Cookie。
检测技术概览
基本JavaScript API检查(误导性)
如前所述,navigator.cookieEnabled
或在主页面上设置document.cookie
无法反映跨站点Cookie状态。这些检查仅适用于第一方,应避免用于检测。
服务器辅助Cookie探测(重量级)
经典方法包括通过HTTP从第三方域设置Cookie,然后检查是否返回。这种方法有效,但需要自定义服务器端逻辑,增加开发和基础设施复杂性。
存储访问API(补充信号)
document.hasStorageAccess()
方法允许嵌入的第三方内容检查是否有权访问未分区的Cookie。这个API在检测Cookie是否存在但被分区的场景中特别有用,但目前最好用作补充信号,而不是独立检查。
iframe + postMessage(最佳实践)
尽管存在存储访问API,但这仍然是最可靠和浏览器兼容的方法:
- 嵌入来自第三方域的隐藏iframe
- 在iframe内尝试设置测试Cookie
- 使用
window.postMessage
向父页面报告成功或失败
逐步实现:通过iframe检测第三方Cookie
步骤1:创建Cookie测试页面
在第三方域上创建一个简单的HTML页面(例如:https://cookietest.example.com/cookie-check.html
):
<!DOCTYPE html>
<html>
<body>
<script>
document.cookie = "thirdparty_test=1; SameSite=None; Secure; Path=/;";
const cookieFound = document.cookie.includes("thirdparty_test=1");
const sendResult = (status) => window.parent?.postMessage(status, "*");
if (cookieFound && document.hasStorageAccess instanceof Function) {
document.hasStorageAccess().then((hasAccess) => {
sendResult(hasAccess ? "TP_COOKIE_SUPPORTED" : "TP_COOKIE_BLOCKED");
}).catch(() => sendResult("TP_COOKIE_BLOCKED"));
} else {
sendResult(cookieFound ? "TP_COOKIE_SUPPORTED" : "TP_COOKIE_BLOCKED");
}
</script>
</body>
</html>
步骤2:嵌入iframe并监听结果
在主页面上:
function checkThirdPartyCookies() {
return new Promise((resolve) => {
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = "https://cookietest.example.com/cookie-check.html";
document.body.appendChild(iframe);
let resolved = false;
const cleanup = (result, timedOut = false) => {
if (resolved) return;
resolved = true;
window.removeEventListener('message', onMessage);
iframe.remove();
resolve({ thirdPartyCookiesEnabled: result, timedOut });
};
const onMessage = (event) => {
if (["TP_COOKIE_SUPPORTED", "TP_COOKIE_BLOCKED"].includes(event.data)) {
cleanup(event.data === "TP_COOKIE_SUPPORTED", false);
}
};
window.addEventListener('message', onMessage);
setTimeout(() => cleanup(false, true), 1000);
});
}
步骤3:使用存储访问API增强检测
在Safari中,即使第三方Cookie被阻止,用户也可以通过存储访问API手动授予访问权限,但只能响应用户手势。
第三方Cookie被阻止时的回退策略
基于重定向的流程
对于身份验证相关流程,从嵌入iframe转换为顶级重定向。让用户直接在身份提供商的站点上进行身份验证,然后重定向回来。
请求存储访问
在明确的UI手势后使用requestStorageAccess()
提示用户(Safari需要这样做)。
基于令牌的通信
通过以下方式直接从父页面向iframe传递会话信息:
postMessage
(需要正确的origin)- 查询参数(例如,iframe URL中的签名JWT)
分区Cookie(CHIPS)
Chrome(自版本114起)和其他基于Chromium的浏览器现在支持带有Partitioned
属性的Cookie,允许按顶级站点进行Cookie隔离。
总结
第三方Cookie正在消失,虽然过程是渐进和不均匀的。在转换完成之前,作为开发者,你的工作是在技术限制和真实用户体验之间架起桥梁。这意味着:
- 关注标准:FedCM和隐私沙盒功能正在重塑我们如何处理身份和分析,而不依赖跨站点Cookie。
- 结合检测与优雅回退:无论是提供重定向流程、使用
requestStorageAccess()
,还是回退到基于令牌的消息传递,每一个小的UX改进都会累积。 - 告知用户:用户不应该被留在那里想知道为什么某个功能在一个浏览器中工作,但在另一个浏览器中无声地失败。
使用htmlpage:强大的HTML在线构建器,免费在线快速创建网页:https://htmlpage.cn/builder,支持源码导出!