大家好,我是Echa。
最近小编一直在关注谷歌官方浏览器 Chrome,就在前段时间谷歌Chrome 团队正式发布了六年磨一剑的WebGPU,借助现代 GPU 的计算能力来加速图形和计算并且允许在 Web 上进行高性能 3D 图形和数据并行计算。当时业界圈内一片哗然——重磅!谷歌正式发布 WebGPU
这次谷歌 Chrome 又接二连三的发布了Chrome 113、114两个版本,都有提到关于 Cookie 的访问方式变化:
Chrome 113:Cookie 第一方集(First-Party Sets)进入稳定版本;
Chrome 114:Cookie 独立分区(CHIPS)默认对所有浏览器启用;
为啥小编特意截上面两张Chrome 官方的图出来,因为这两个都是针对 Cookie 访问方式的大调整,为的就是应对即将来临的三方 Cookie 全面弃用。Chrome在两年前就已经计划全面弃用方 Cookie 了,因为这个变化对现在的网站影响太大了,如果直接弃用,可能会导致大量网站的正常功能无法正常使用。
另外对Google本身的广告业务也有非常大的影响,所以Chrome不得不一拖再拖,为的就是能够推出一套对现有的业务影响不是很大,能够保障用户平稳迁移,又能保护用户隐私的方案。
目前看来,随着 Cookie 第一方集、Cookie 独立分区两项能力的稳定推出,全面禁用三方 Cookie 的那一天似乎不远了,这两项改动确实能够解决一大部分正常使用三方 Cookie 的业务场景,但是 Cookie 的读取方式可能要有大调整了。
今天小编就带着大家来提前解读一下这两项关于 Cookie 的大调整,大家也要提前做好迁移和应对策略,保障未来禁用三方 Cookie 之后网站能够避免受到影响。
首先了解Cookie如何产生、Cookie 分类、Cookie用途、Cookie生命周期
Cookie的生命周期有两种,一种是整个会话的,一种是永久的。也就是说,一种是临时性的Cookie,用户关掉浏览器,这个Cookie也就失效了。一种是永久的Cookie,可以持续存在的。一般网站分析工具 判断Unique Visitor使用的是后者。
千言万语,不如一张完整的图讲解:
第一方和第三方Cookie的区别
Cookie 是属于一方 Cookie、还是三方 Cookie,只取决于两个要素:
- Cookie 是被哪个域名种的
- Cookie 是在哪个网站上种的
第一方Cookie和第三方Cookie,都是网站在客户端上存放的一小块数据。他们都由某个域存放,只能被这个域访问。他们的区别其实并不是技术上的区别,而是使用方式上的区别。
比如,访问www.douyin.com这个网站,这个网站通过set-cookie这个Header设置了一个Cookie,这个Cookie也只能被www.douyin.com 这个域下的网页读取,这就是第一方Cookie。
如果还是访问www.douyin.com这个网站,网页里有用到bytedance.com网站的一张图片,浏览器在向 bytedance.com请求图片的时候,bytedance.com通过set-cookie这个Header设置了一个Cookie,那这个Cookie只能被bytedance.com这个域访问,反而不能被 www.douyin.com这个域访问,因为对我们来说,我们实际是在访问www.douyin.com这个网站被设置了一个bytedance.com个域下的Cookie,所以叫第三方Cookie。
第一方Cookie的优势和应用
第一方Cookie的最大优势是接受率高。一般主流的浏览器的都会有隐私的设置,可以让用户设置是否接受Cookie,接受哪些Cookie。
除了 完全不接受Cookie这个设置以外,其他情况下,第一方Cookie都是会被用户接受的(不接受的话,是没办法把那小块数据保存下来的)。
所以,如果没有特殊要求,使用第一方Cookie会比第三方Cookie,我们通过分析工具得到的数据会更准确。
三方Cookie的优势和应用
第三方Cookie的接受率不如第一方Cookie(不过主流的浏览器默认的设置下也接受带P3P协议的第三方Cookie,我的经验是接受率能达到90%,甚至95%以上),但在某些特定情况下可以实现第一方Cookie无法实现的功能。
比如,当我们有多个域名的网站需要跟踪,我们希望了解到用户 点击某个广告到达域名A下的网页,然后可能浏览了不论那个域名下的页面,最后在域名B下的网页完成注册的情况。广告可以在域名A下的网页被跟踪到,而注册 可以在域名B下的网页跟踪到。
如果我们使用第一方Cookie,会为域名A建立一个Cookie,为域名B再建立一个Cookie,他们可以关联各自域名 下网页上的行为,但是无法关联起来。而使用第三方Cookie,那么无论多少个域,都只有一个Cookie,一个属于第三方域的Cookie,网站下所有域都能共享这个Cookie,那么所有的行为都能被关联起来分析。
三方 Cookie 有啥问题?
我们的网站不可能只调用同站的域名的接口,调用其他域名的接口再正常不过了,所以有三方 Cookie 也是很正常的,我们也通过三方 Cookie 做了很多正常的需求,比如日志打点、单点登录、广告转化分析等等。那为什么要禁用呢?主要还是因为用户隐私的问题。
比如我们现在正在抖音上刷视频,但是抖音上往往会加载很多三方广告商的请求,这些三方广告商就可以通过三方 Cookie 来记录一些用户的行为。然后下次你逛淘宝的时候,也可能再次加载到这个广告商,因为这时三方广告已经通过三方 Cookie 记录了你的很多用户行为,已经知道了你喜欢什么东西,所以你就会收到一些精准的广告推送,无形之中你的隐私已经泄漏出去了。
在海外,用户隐私可是相当ZZ正确的事,所以 Safira、Firefox 两大浏览器已经迫于压力禁用了三方 Cookie,也就是说,如果你在这两个浏览器上去访问www.douyin.com这个网站,那么再发送bytedance.com这个域名的请求是种不上 Cookie 的。
目前就剩下Chrome还在苦苦支撑了,毕竟Chrome现在的浏览器市场份额是最大的,而且直接禁用对它的老板Google的广告业务影响也非常大。所以Chrome需要等待一个大家都可接受的替代方案出来之后再禁用。
为了增加网络隐私,浏览器供应商正在计划或已经对跨站点跟踪进行限制。这包括逐步取消对第三方cookie的支持,即向顶级文档网站以外的网站发送请求的cookie,因为此类cookie使服务器能够跟踪用户在不同顶级网站上的行为。
在cookie之前:浏览器访问green.com,它有一个嵌入的red.com框架,可以设置cookie。当浏览器导航到blue.com时,red.com框架可以访问green.com上设置的cookie。
两个可能遇到问题的场景
对于我们普通开发者来说,其实还是有很多场景可能会受到影响的,我们也必须在禁用之前作出相应的改变,比如下面两个场景。
三方 iframe Cookie
第一个场景是我们需要和嵌入的三方 iframe 共享状态。假如我们现在开发了一个通用的聊天服务,它的域名是support.chat.example,我们有很多业务网站(比如retail.example) 希望用iframe的方式嵌入这个聊天框。这个嵌入式的聊天服务可能会依赖Cookie来保存用户的交互历史记录。因为我们嵌入的iframe域名和当前的网站是夸站的,所以iframe种下的Cookie就属于三方Cookie。
假如现在没有了设置跨站点三方Cookie的能力,那我们的聊天服务support.chat.example可能需要更依赖父级网站retail.example主动传递给他们第一方会话的一些标识符。因为这种聊天服务往往都是通用的,所以相应的每个嵌入support.chat.example聊天服务的网站都需要额外的设置来传递状态,这大大增加了开发和接入成本。
或者,我们也可以允许聊天服务support.chat.example请求我们的网站retail.example页面上的JavaScript。但是这又引入了非常大的安全风险,也不是个靠谱的方法。类似可能遇到的场景还包括:
- 三方地图服务
- 子资源CDN负载均衡
- Headless CMS提供商
- 不信任的用户内容的沙盒域名
- 三方嵌入式广告
三方站点 Cookie
另外还有一个场景,根据域名的不同来定义 Cookie 属于第三方有点太狭隘了,毕竟一个公司不可能只有一个域名:
比如上面我们提到的www.douyin.com和www.bytedance.com,虽然域名不一样,种的 Cookie 也叫做三方 Cookie,但是明眼人都能看出来,抖音就是字节的,这俩域名就是一家的。
如果禁用了三方 Cookie ,那这种正常的在一家公司不同域名下共享 Cookie 的能力也就不能用了,这给正常的业务需求会带来很大的影响,一个常见的场景就是单点登录,我们往往在登陆一家公司的不同网站的时候只需要登录一次,这是因为用户的个人信息存储在了一个公共的登录服务的 Cookie 上,禁用了三方 Cookie,那登录信息也就无法共享了。下面我们来看看如何解决以上的两个问题。
Cookie 独立分区(CHIPS)
首先我们来看 Chrome 114 默认对所有用户启用的 Cookie 独立分区(CHIPS),这就是用来解决三方 iframe 共享状态的问题的。
如何解决问题?
具有独立分区状态的Cookie (CHIPS),它允许开发者将 Cookie 选择到“分区”存储中,每个顶级站点都有单独的Cookie jar。
Chrome 官方是这样描述它的:CHIPS 是帮助服务顺利过渡到没有第三方 Cookie 的未来的重要一步。
CHIPS引入了一个新的Cookie属性:Partitioned,它可以让顶级上下文分决定哪些Cookie进行分区。
举个例子,假如我们在站点 A 中通过iframe嵌入了一个站点 C,正常情况下如果三方Cookie被禁用后,C 是无法在 A 站点访问到它的Cookie的。
如果 C 在它的Cookie上指定了Partitioned属性,这个 Cookie 将保存在一个特殊的分区 jar 中。它只会在站点 A 中通过 iframe 嵌入站点 C 时才会生效,浏览器会判定只会在顶级站点为 A 时才发送该 Cookie。
当用户访问一个新站点时,例如站点 B,如果也它通过 iframe 嵌入了站点 C,这时在站点 B 下的站点 C 是无法访问到之前在 A 下面设置的那个 Cookie 的。
如果用户直接访问站点 C ,一样也是访问不到这个 Cookie 的。
这样就在保障用户隐私的情况下解决了三方 iframe Cookie 共享的问题。
如何使用?
实施方式也非常简单,就像上面说的,想要在当前网站上保留需要共享的三方Cookie,只需要在种这个 Cookie 的时候添加一个Partitioned属性,另外还有个前提是Cookie必须具有Secure属性:
Set-Cookie: name=ConardLi; SameSite=None; Secure; Path=/; Partitioned;
实现细节
Partitioned属性实际上是改变了 Cookie 存储分区的机制,让分区更加严格了,还是上面的例子,我们将一个https://support.chat.exampleiframe嵌入在页面https://retail.example上,在启用Partitioned之前,Cookie 分区的唯一标识是:support.chat.example,而启用了Partitioned之后,分区的唯一标识变成了("https", "retail.example") + support.chat.example。
Firefox在它的ETP严格模式和隐私浏览模式下默认对所有第三方cookie进行了分区,所以所有的跨站cookie都会默认按照顶级站点进行分区。但是,在没有第三方选择加入的情况下对cookie进行分区可能会导致一些意外的问题,因为在某些特定场景下可能也会用到未分区的第三方cookie。
Safari之前也曾尝试过一些Cookie分区的机制,但最终还是放弃了,目前完全阻止了三方Cookie,理由之一是开发者可能会感到困惑。。不过目前好像又开始做一些Cookie分区的实验了。
目前我觉得Chrome提供的这种启发式Cookie分区的思路还挺好用的,既解决了跨站跟踪的问题,而且也能在一定程度上满足用户需求,希望其他浏览器也借鉴一下吧。
Cookie 第一方集(First-Party Sets)
上面我们解决了三方 iframe 状态共享的问题,下面我们提到的Cookie First-Party Sets则是用来解决自定义 Cookie 集合的问题,也就是说提供了一种选择性的把一些Cookie从三方变为一方的方式。
如何解决问题?
前面我们提到了,很多组织或公司都会有多个域名,所以只用域名的不同来区分 Cookie 属于第一方还是第三方这种方式太严格了。
First-Party Sets相当于给了网站开发者一个机会,有一些 Cookie 虽然根据域名的划分是第三方的,但是你可以自己选择指定一部分 Cookie 把它们放在一个集合里,在这个集合里的三方 Cookie 都可以按照一种特殊的形式来读取到。
换个角度讲,douyin.com、bytedance.com这两个域名虽然是属于同一个组织,但是Chrome不知道,你可以通过把它们放到一个集合里来告诉Chrome这些不同的域名属于同一个组织。
如何使用?
根据上面的解决问题的思路,想要实现First-Party Sets就需要两步:
- 第一步:把想要共享 Cookie 的不同域名放到一个集合里,然后提交给 Chrome;
- 第二步:使用 Chrome 提供的特殊的方式来读取这些域名集合下共享的 Cookie;
在早期的提案中,为Cookie新增了一个samePaty属性,你可以通过这个属性来告诉浏览器哪些 Cookie 是需要三方共享的,然后需要把共享的域名集合放到网站的部署目录下。
但是,这种方式的限制有点过于宽松了,网站可以很轻松的再次实现三方 Cookie 共享,共享的策略也不够透明,所以 Chrome 决定弃用了这种方案,转而实现了一种更复杂的方式。
首先你需要给出一份 JSON 文件,在这个文件里声明哪些域名是需要共享Cookie的,然后你需要把这个 JSON 文件通过Pull Request提交到Chrome提供的一个Github仓库中:https://github.com/GoogleChrome/first-party-sets
而且要求 JSON 文件的格式必须符合规范,下面是一个例子:
{
"primary": "https://primary.com",
"associatedSites": ["https://associate1.com", "https://associate2.com", "https://associate3.com", "https://associate4.com"],
"serviceSites": ["https://servicesite1.com"],
"rationaleBySite": {
"https://associate1.com": "An explanation of how you clearly present the affiliation across domains to users and why users would expect your domains to be affiliated",
"https://associate2.com": "An explanation of how you clearly present the affiliation across domains to users and why users would expect your domains to be affiliated",
"https://associate3.com": "An explanation of how you clearly present the affiliation across domains to users and why users would expect your domains to be affiliated",
"https://serviceSite1.com": "An explanation of how each domain in this subset supports functionality or security needs."
},
"ccTLDs": {
"https://associate1.com": ["https://associate1.ca", "https://associate1.co.uk", "https://associate1.de"],
"https://associate2.com": ["https://associate2.ru", "https://associate2.co.kr", "https://associate2.fr"],
"https://primary.com": ["https://primary.co.uk"]
}
}
在这其中有几个关键的概念:
- ccTLDs域名:网站可能服务于不同的国家,在每个地区都有一个特定的域名,比如conardli.cn、conardli.jp、conardli.en等等;
- Service域名:网站可能会使用特定的域名来保证安全性或者提高性能,但是这些不同域名的网站可能也需要共享用户身份。
- Associated域名:同一个组织下可能有多个不同的子品牌,对应不同的域名,例如bytedance.com、douyin.com就属于这种情况。
提交完PR之后,Google团队会在每个周二的中午 12 点手动Review并且合并这些PR。(这里我也不知道Chrome团队是咋想的。。。后面网站多了之后肯定每天都有大量的 PR,这种维护方式真的可行么??)
等到你的 JSON 配置被 Chrome 团队 Merge 后,也不是就代表着你可以随意在这些域名下共享三方 Cookie 了,你还需要用到一个特殊的Storage Access API(SAA),下面是一份演示代码:
http://www.zzvips.com/uploads/allimg/abybgys2c2j API:
/*
* 通过 UA 判断浏览器版本
*/
if (navigator.userAgentData.brands.some(b => { return b.brand === 'Google Chrome' && parseInt(b.version, 10) >= 108 })) {
// Supported
} else {
// Not supported
}
/*
* 判断 SAA 和 rSAFor API 是否可用
*/
if ('requestStorageAccess' in document) {
// SAA available
} else {
// SAA not available
}
if ('requestStorageAccessForOrigin' in document) {
// rSAFor available
} else {
// rSAFor not available
}
通过requestStorageAccess来判断用户是否授予了对三方Cookie的访问权限,并且访问所有可以读取到的Cookie:
if ('requestStorageAccess' in document) {
document.requestStorageAccess().then(
(res) => { console.log('权限请求通过', res) },
(err) => { console.log('拒绝', err) }
);
}
通过requestStorageAccessForOrigin来读取指定域名下共享的的三方Cookie:
if ('requestStorageAccessForOrigin' in document) {
document.requestStorageAccessForOrigin('https://first-party-sets.glitch.me');
location.reload();
} else {
window.alert('document.requestStorageAccessForOrigin not enabled.');
}
最后
一台电脑,一个键盘,尽情挥洒智慧的人生;几行数字,几个字母,认真编写生活的美好;
一 个灵感,一段程序,推动科技进步,促进社会发展。