谷歌 Chrome: Cookie 訪問方式大調(diào)整
大家好,我是Echa。
最近小編一直在關(guān)注谷歌官方瀏覽器 Chrome,就在前段時間谷歌 Chrome 團隊正式發(fā)布了六年磨一劍的WebGPU,借助現(xiàn)代 GPU 的計算能力來加速圖形和計算并且允許在 Web 上進行高性能 3D 圖形和數(shù)據(jù)并行計算。當時業(yè)界圈內(nèi)一片嘩然——重磅!谷歌正式發(fā)布 WebGPU
這次谷歌 Chrome 又接二連三的發(fā)布了Chrome 113、114 兩個版本,都有提到關(guān)于 Cookie 的訪問方式變化:
Chrome 113:Cookie 第一方集(First-Party Sets)進入穩(wěn)定版本;
Chrome 114:Cookie 獨立分區(qū)(CHIPS)默認對所有瀏覽器啟用;
Chrome 113 First-Party Sets
Chrome 114 :Cookie 獨立分區(qū)(CHIPS)
為啥小編特意截上面兩張Chrome 官方的圖出來,因為這兩個都是針對 Cookie 訪問方式的大調(diào)整,為的就是應(yīng)對即將來臨的三方 Cookie 全面棄用。Chrome 在兩年前就已經(jīng)計劃全面棄用方 Cookie 了,因為這個變化對現(xiàn)在的網(wǎng)站影響太大了,如果直接棄用,可能會導致大量網(wǎng)站的正常功能無法正常使用。
另外對 Google 本身的廣告業(yè)務(wù)也有非常大的影響,所以 Chrome 不得不一拖再拖,為的就是能夠推出一套對現(xiàn)有的業(yè)務(wù)影響不是很大,能夠保障用戶平穩(wěn)遷移,又能保護用戶隱私的方案。
目前看來,隨著 Cookie 第一方集、Cookie 獨立分區(qū)兩項能力的穩(wěn)定推出,全面禁用三方 Cookie 的那一天似乎不遠了,這兩項改動確實能夠解決一大部分正常使用三方 Cookie 的業(yè)務(wù)場景,但是 Cookie 的讀取方式可能要有大調(diào)整了。
今天小編就帶著大家來提前解讀一下這兩項關(guān)于 Cookie 的大調(diào)整,大家也要提前做好遷移和應(yīng)對策略,保障未來禁用三方 Cookie 之后網(wǎng)站能夠避免受到影響。
首先了解Cookie如何產(chǎn)生、Cookie 分類、Cookie用途、Cookie生命周期
Cookie的生命周期有兩種,一種是整個會話的,一種是永久的。也就是說,一種是臨時性的Cookie,用戶關(guān)掉瀏覽器,這個Cookie也就失效了。一種是永久的Cookie,可以持續(xù)存在的。一般網(wǎng)站分析工具 判斷Unique Visitor使用的是后者。
千言萬語,不如一張完整的圖講解:
第一方和第三方Cookie的區(qū)別
Cookie 是屬于一方 Cookie、還是三方 Cookie,只取決于兩個要素:
- Cookie 是被哪個域名種的
- Cookie 是在哪個網(wǎng)站上種的
第一方Cookie和第三方Cookie,都是網(wǎng)站在客戶端上存放的一小塊數(shù)據(jù)。他們都由某個域存放,只能被這個域訪問。他們的區(qū)別其實并不是技術(shù)上的區(qū)別,而是使用方式上的區(qū)別。
比如,訪問www.douyin.com這個網(wǎng)站,這個網(wǎng)站通過set-cookie 這個 Header設(shè)置了一個Cookie,這個Cookie也只能被www.douyin.com 這個域下的網(wǎng)頁讀取,這就是第一方Cookie。
如果還是訪問www.douyin.com這個網(wǎng)站,網(wǎng)頁里有用到bytedance.com網(wǎng)站的一張圖片,瀏覽器在向 bytedance.com請求圖片的時候,bytedance.com通過set-cookie 這個 Header 設(shè)置了一個Cookie,那這個Cookie只能被bytedance.com這個域訪問,反而不能被 www.douyin.com這個域訪問,因為對我們來說,我們實際是在訪問www.douyin.com這個網(wǎng)站被設(shè)置了一個bytedance.com個域下的Cookie,所以叫第三方Cookie。
第一方Cookie的優(yōu)勢和應(yīng)用
第一方Cookie的最大優(yōu)勢是接受率高。一般主流的瀏覽器的都會有隱私的設(shè)置,可以讓用戶設(shè)置是否接受Cookie,接受哪些Cookie。
除了 完全不接受Cookie這個設(shè)置以外,其他情況下,第一方Cookie都是會被用戶接受的(不接受的話,是沒辦法把那小塊數(shù)據(jù)保存下來的)。
所以,如果沒有特殊要求,使用第一方Cookie會比第三方Cookie,我們通過分析工具得到的數(shù)據(jù)會更準確。
三方Cookie的優(yōu)勢和應(yīng)用
第三方Cookie的接受率不如第一方Cookie(不過主流的瀏覽器默認的設(shè)置下也接受帶P3P協(xié)議的第三方Cookie,我的經(jīng)驗是接受率能達到90%,甚至95%以上),但在某些特定情況下可以實現(xiàn)第一方Cookie無法實現(xiàn)的功能。
比如,當我們有多個域名的網(wǎng)站需要跟蹤,我們希望了解到用戶 點擊某個廣告到達域名A下的網(wǎng)頁,然后可能瀏覽了不論那個域名下的頁面,最后在域名B下的網(wǎng)頁完成注冊的情況。廣告可以在域名A下的網(wǎng)頁被跟蹤到,而注冊 可以在域名B下的網(wǎng)頁跟蹤到。
如果我們使用第一方Cookie,會為域名A建立一個Cookie,為域名B再建立一個Cookie,他們可以關(guān)聯(lián)各自域名 下網(wǎng)頁上的行為,但是無法關(guān)聯(lián)起來。而使用第三方Cookie,那么無論多少個域,都只有一個Cookie,一個屬于第三方域的Cookie,網(wǎng)站下所有域都能共享這個Cookie,那么所有的行為都能被關(guān)聯(lián)起來分析。
三方 Cookie 有啥問題?
我們的網(wǎng)站不可能只調(diào)用同站的域名的接口,調(diào)用其他域名的接口再正常不過了,所以有三方 Cookie 也是很正常的,我們也通過三方 Cookie 做了很多正常的需求,比如日志打點、單點登錄、廣告轉(zhuǎn)化分析等等。那為什么要禁用呢?主要還是因為用戶隱私的問題。
比如我們現(xiàn)在正在抖音上刷視頻,但是抖音上往往會加載很多三方廣告商的請求,這些三方廣告商就可以通過三方 Cookie 來記錄一些用戶的行為。然后下次你逛淘寶的時候,也可能再次加載到這個廣告商,因為這時三方廣告已經(jīng)通過三方 Cookie 記錄了你的很多用戶行為,已經(jīng)知道了你喜歡什么東西,所以你就會收到一些精準的廣告推送,無形之中你的隱私已經(jīng)泄漏出去了。
在海外,用戶隱私可是相當ZZ正確的事,所以 Safira、Firefox 兩大瀏覽器已經(jīng)迫于壓力禁用了三方 Cookie,也就是說,如果你在這兩個瀏覽器上去訪問 www.douyin.com 這個網(wǎng)站,那么再發(fā)送 bytedance.com 這個域名的請求是種不上 Cookie 的。
目前就剩下 Chrome 還在苦苦支撐了,畢竟 Chrome 現(xiàn)在的瀏覽器市場份額是最大的,而且直接禁用對它的老板 Google 的廣告業(yè)務(wù)影響也非常大。所以 Chrome 需要等待一個大家都可接受的替代方案出來之后再禁用。
為了增加網(wǎng)絡(luò)隱私,瀏覽器供應(yīng)商正在計劃或已經(jīng)對跨站點跟蹤進行限制。這包括逐步取消對第三方cookie的支持,即向頂級文檔網(wǎng)站以外的網(wǎng)站發(fā)送請求的cookie,因為此類cookie使服務(wù)器能夠跟蹤用戶在不同頂級網(wǎng)站上的行為。
在cookie之前:瀏覽器訪問green.com,它有一個嵌入的red.com框架,可以設(shè)置cookie。當瀏覽器導航到blue.com時,red.com框架可以訪問green.com上設(shè)置的cookie。
兩個可能遇到問題的場景
對于我們普通開發(fā)者來說,其實還是有很多場景可能會受到影響的,我們也必須在禁用之前作出相應(yīng)的改變,比如下面兩個場景。
三方 iframe Cookie
第一個場景是我們需要和嵌入的三方 iframe 共享狀態(tài)。假如我們現(xiàn)在開發(fā)了一個通用的聊天服務(wù),它的域名是 support.chat.example,我們有很多業(yè)務(wù)網(wǎng)站(比如 retail.example) 希望用 iframe 的方式嵌入這個聊天框。這個嵌入式的聊天服務(wù)可能會依賴 Cookie 來保存用戶的交互歷史記錄。因為我們嵌入的 iframe 域名和當前的網(wǎng)站是夸站的,所以 iframe 種下的 Cookie 就屬于三方 Cookie。
假如現(xiàn)在沒有了設(shè)置跨站點三方 Cookie 的能力,那我們的聊天服務(wù) support.chat.example 可能需要更依賴父級網(wǎng)站 retail.example 主動傳遞給他們第一方會話的一些標識符。因為這種聊天服務(wù)往往都是通用的,所以相應(yīng)的每個嵌入 support.chat.example 聊天服務(wù)的網(wǎng)站都需要額外的設(shè)置來傳遞狀態(tài),這大大增加了開發(fā)和接入成本。
或者,我們也可以允許聊天服務(wù) support.chat.example 請求我們的網(wǎng)站 retail.example 頁面上的 JavaScript。但是這又引入了非常大的安全風險,也不是個靠譜的方法。類似可能遇到的場景還包括:
- 三方地圖服務(wù)
- 子資源 CDN 負載均衡
- Headless CMS 提供商
- 不信任的用戶內(nèi)容的沙盒域名
- 三方嵌入式廣告
三方站點 Cookie
另外還有一個場景,根據(jù)域名的不同來定義 Cookie 屬于第三方有點太狹隘了,畢竟一個公司不可能只有一個域名:
比如上面我們提到的 www.douyin.com 和 www.bytedance.com ,雖然域名不一樣,種的 Cookie 也叫做三方 Cookie,但是明眼人都能看出來,抖音就是字節(jié)的,這倆域名就是一家的。
如果禁用了三方 Cookie ,那這種正常的在一家公司不同域名下共享 Cookie 的能力也就不能用了,這給正常的業(yè)務(wù)需求會帶來很大的影響,一個常見的場景就是單點登錄,我們往往在登陸一家公司的不同網(wǎng)站的時候只需要登錄一次,這是因為用戶的個人信息存儲在了一個公共的登錄服務(wù)的 Cookie 上,禁用了三方 Cookie,那登錄信息也就無法共享了。下面我們來看看如何解決以上的兩個問題。
Cookie 獨立分區(qū)(CHIPS)
首先我們來看 Chrome 114 默認對所有用戶啟用的 Cookie 獨立分區(qū)(CHIPS),這就是用來解決三方 iframe 共享狀態(tài)的問題的。
如何解決問題?
具有獨立分區(qū)狀態(tài)的 Cookie (CHIPS) ,它允許開發(fā)者將 Cookie 選擇到“分區(qū)”存儲中,每個頂級站點都有單獨的 Cookie jar。
Chrome 官方是這樣描述它的:CHIPS 是幫助服務(wù)順利過渡到?jīng)]有第三方 Cookie 的未來的重要一步。
CHIPS 引入了一個新的 Cookie 屬性:Partitioned ,它可以讓頂級上下文分決定哪些 Cookie 進行分區(qū)。
舉個例子,假如我們在站點 A 中通過 iframe 嵌入了一個站點 C,正常情況下如果三方 Cookie 被禁用后,C 是無法在 A 站點訪問到它的 Cookie 的。
如果 C 在它的 Cookie 上指定了 Partitioned 屬性,這個 Cookie 將保存在一個特殊的分區(qū) jar 中。它只會在站點 A 中通過 iframe 嵌入站點 C 時才會生效,瀏覽器會判定只會在頂級站點為 A 時才發(fā)送該 Cookie。
當用戶訪問一個新站點時,例如站點 B,如果也它通過 iframe 嵌入了站點 C,這時在站點 B 下的站點 C 是無法訪問到之前在 A 下面設(shè)置的那個 Cookie 的。
如果用戶直接訪問站點 C ,一樣也是訪問不到這個 Cookie 的。
這樣就在保障用戶隱私的情況下解決了三方 iframe Cookie 共享的問題。
如何使用?
實施方式也非常簡單,就像上面說的,想要在當前網(wǎng)站上保留需要共享的三方 Cookie ,只需要在種這個 Cookie 的時候添加一個 Partitioned 屬性,另外還有個前提是 Cookie 必須具有 Secure 屬性:
Set-Cookie: name=ConardLi; SameSite=None; Secure; Path=/; Partitioned;
實現(xiàn)細節(jié)
Partitioned 屬性實際上是改變了 Cookie 存儲分區(qū)的機制,讓分區(qū)更加嚴格了,還是上面的例子,我們將一個 https://support.chat.example iframe 嵌入在頁面 https://retail.example 上,在啟用 Partitioned 之前,Cookie 分區(qū)的唯一標識是:support.chat.example ,而啟用了Partitioned之后,分區(qū)的唯一標識變成了 ("https", "retail.example") + support.chat.example。
Firefox 在它的 ETP 嚴格模式和隱私瀏覽模式下默認對所有第三方 cookie 進行了分區(qū),所以所有的跨站 cookie 都會默認按照頂級站點進行分區(qū)。但是,在沒有第三方選擇加入的情況下對 cookie 進行分區(qū)可能會導致一些意外的問題,因為在某些特定場景下可能也會用到未分區(qū)的第三方 cookie。
Safari 之前也曾嘗試過一些 Cookie 分區(qū)的機制,但最終還是放棄了,目前完全阻止了三方 Cookie,理由之一是開發(fā)者可能會感到困惑。。不過目前好像又開始做一些 Cookie 分區(qū)的實驗了。
目前我覺得 Chrome 提供的這種啟發(fā)式 Cookie 分區(qū)的思路還挺好用的,既解決了跨站跟蹤的問題,而且也能在一定程度上滿足用戶需求,希望其他瀏覽器也借鑒一下吧。
Cookie 第一方集(First-Party Sets)
上面我們解決了三方 iframe 狀態(tài)共享的問題,下面我們提到的 Cookie First-Party Sets 則是用來解決自定義 Cookie 集合的問題,也就是說提供了一種選擇性的把一些 Cookie 從三方變?yōu)橐环降姆绞健?/p>
如何解決問題?
前面我們提到了,很多組織或公司都會有多個域名,所以只用域名的不同來區(qū)分 Cookie 屬于第一方還是第三方這種方式太嚴格了。
First-Party Sets 相當于給了網(wǎng)站開發(fā)者一個機會,有一些 Cookie 雖然根據(jù)域名的劃分是第三方的,但是你可以自己選擇指定一部分 Cookie 把它們放在一個集合里,在這個集合里的三方 Cookie 都可以按照一種特殊的形式來讀取到。
換個角度講,douyin.com、bytedance.com 這兩個域名雖然是屬于同一個組織,但是 Chrome 不知道,你可以通過把它們放到一個集合里來告訴 Chrome 這些不同的域名屬于同一個組織。
如何使用?
根據(jù)上面的解決問題的思路,想要實現(xiàn) First-Party Sets 就需要兩步:
- 第一步:把想要共享 Cookie 的不同域名放到一個集合里,然后提交給 Chrome;
- 第二步:使用 Chrome 提供的特殊的方式來讀取這些域名集合下共享的 Cookie;
在早期的提案中,為 Cookie 新增了一個 samePaty 屬性,你可以通過這個屬性來告訴瀏覽器哪些 Cookie 是需要三方共享的,然后需要把共享的域名集合放到網(wǎng)站的部署目錄下。
但是,這種方式的限制有點過于寬松了,網(wǎng)站可以很輕松的再次實現(xiàn)三方 Cookie 共享,共享的策略也不夠透明,所以 Chrome 決定棄用了這種方案,轉(zhuǎn)而實現(xiàn)了一種更復(fù)雜的方式。
首先你需要給出一份 JSON 文件,在這個文件里聲明哪些域名是需要共享 Cookie 的,然后你需要把這個 JSON 文件通過 Pull Request 提交到 Chrome 提供的一個 Github 倉庫中:https://github.com/GoogleChrome/first-party-sets
而且要求 JSON 文件的格式必須符合規(guī)范,下面是一個例子:
{
"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"]
}
}
在這其中有幾個關(guān)鍵的概念:
- ccTLDs 域名:網(wǎng)站可能服務(wù)于不同的國家,在每個地區(qū)都有一個特定的域名,比如 conardli.cn、conardli.jp、conardli.en 等等;
- Service 域名:網(wǎng)站可能會使用特定的域名來保證安全性或者提高性能,但是這些不同域名的網(wǎng)站可能也需要共享用戶身份。
- Associated 域名:同一個組織下可能有多個不同的子品牌,對應(yīng)不同的域名,例如 bytedance.com、douyin.com 就屬于這種情況。
提交完 PR 之后,Google 團隊會在每個周二的中午 12 點手動 Review 并且合并這些 PR。(這里我也不知道 Chrome 團隊是咋想的。。。后面網(wǎng)站多了之后肯定每天都有大量的 PR,這種維護方式真的可行么??)
等到你的 JSON 配置被 Chrome 團隊 Merge 后,也不是就代表著你可以隨意在這些域名下共享三方 Cookie 了,你還需要用到一個特殊的 Storage Access API(SAA) ,下面是一份演示代碼:
https://glitch.com/edit/#!/first-party-sets
我們來拆解一下,首先是判斷瀏覽器是否支持這個 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 的訪問權(quán)限,并且訪問所有可以讀取到的 Cookie:
if ('requestStorageAccess' in document) {
document.requestStorageAccess().then(
(res) => { console.log('權(quán)限請求通過', 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.');
}
最后
一臺電腦,一個鍵盤,盡情揮灑智慧的人生;幾行數(shù)字,幾個字母,認真編寫生活的美好;
一 個靈感,一段程序,推動科技進步,促進社會發(fā)展。