如何使用 JavaScript 檢測用戶是否啓用三方 Cookie ?
大家好,我是 ConardLi。
今天繼續來聊 Cookie
,Chrome
已經在 1.4
號開啓了三方 Cookie
的 1%
禁用灰度:
不少小夥伴反饋已經命中了這個灰度,因爲時間比較急,很多網站來不及改造,很多網站的正常功能在這個灰度策略下受到了影響。
在前面的文章中我們提到,對於一些還沒來得及改造完的網站,Chrome
提供了一種便捷的方式來讓命中灰度的用戶手動關閉這個策略:
這個開關點擊後可以允許指定域名繼續使用三方 Cookie
,但是這個期限只有 90 天。
所以,如果大家的網站最近沒有時間進行這些改造,大家可以在運行時來提示用戶手動關閉三方 Cookie
的禁用策略。
那麼問題來了,並不是所有用戶都命中了這個策略,當前只有 1%
,我們可能給所有的用戶都添加這個提示,所以我們如何在運行時檢測用戶是否命中了三方 Cookie
的灰度策略呢?
function checkCookie(){
var cookieEnabled = navigator.cookieEnabled;
if (!cookieEnabled){
document.cookie = "testcookie";
cookieEnabled = document.cookie.indexOf("testcookie")!=-1;
}
return cookieEnabled || showCookieFail();
}
function showCookieFail(){
// do something here
}
checkCookie();
上面的代碼片段可用於檢查 Cookie
是否啓用,但是對三方 Cookie
的檢查就無能爲力了,三方 Cookie
禁用的情況下還是會返回 true
。
我能想到的並且一直有效的方法就是添加一個外部(三方)的 iFrame
,讓它來檢測 iFrame
內部是否可以訪問到 Cookie
,並且會將 Cookie
的可用狀態通知給父應用。
雖然這聽起來挺奇怪的,我們好像無法直接通過 iFrame
調用父頁面的功能。但是我們可以使用 Message Event
來進行父子應用之間的通信,通過這個我們可以基於 URL
向其他瀏覽器發送消息,在我們現在這種情況下,我們可以從 iFrame
向可能在不同域上的父應用發送消息。
首先,我們在 iFrame
內添加一個立即執行函數。在這個函數中,我們添加一個消息事件監聽器,這個監聽器會在從父級應用程序調用時觸發。當被調用時,它首先會驗證請求,然後調用 checkCookiesEnable
函數來檢查 Cookie
的狀態並返回結果。然後,我們通過 parent.postMessage()
方法向父應用發送一條消息;在 iFrame
中,parent
是一個隱含的對象。
<!doctype html>
<html>
<head>
</head>
<body>
<script>
const checkCookiesEnable = () => {
let isCookieEnabled = (window.navigator.cookieEnabled) ? true : false;
if (typeof window.navigator.cookieEnabled == "undefined" && !isCookieEnabled) {
// 嘗試設置一個測試cookie
document.cookie = "testcookie";
// 檢查cookie是否已設置
isCookieEnabled = (document.cookie.indexOf("testcookie") != -1) ? true : false;
}
return isCookieEnabled;
}
// 監聽消息事件,響應從父窗口傳來的消息
(function () {
window.addEventListener('message', event => {
try {
let data = JSON.parse(event.data)
if (data['test'] !== 'cookie')
return
let result = checkCookiesEnable();
// 將結果通過消息事件發送到父窗口
parent.postMessage(JSON.stringify({
'result': result
}), event.origin);
}
catch (e) {
console.error(e)
}
});
})();
</script>
</body>
</html>
在這裏,我們將添加一個消息事件處理程序,然後在插入任何第三方腳本之前插入我們的 iFrame
。一旦 iFrame
加載完畢,我們將通過 frame.contentWindow
對象向我們的 iFrame
發送 postMessage
,使用 "*"
允許 postMessage
任何來源(不同的域)。
然後,iFrame
內部的函數檢查iFrame
的 Cookie
狀態併發送一個消息,該消息被我們的 messagehandler
攔截。檢查消息是否由 iFrame
發送,事件現在將保存來自 iFrame
內的 checkCookieEnable
函數結果的響應。
下面是一個示例函數,它接受 iframeUri 和一個回調函數,在收到結果後將被調用。
const cookieTest = (iFrameUri, callBack) => {
let messageHandler = (event) => {
// 在這裏檢查受信任的來源
const data = JSON.parse(event.data);
callBack(data['result']);
window.removeEventListener('message', messageHandler);
document.body.removeChild(frame);
};
// 監聽消息事件,響應從 iframe 窗口傳來的消息
window.addEventListener('message', messageHandler);
// 創建並添加一個隱藏的 iframe 元素
const frame = document.createElement('iframe');
frame.src = iFrameUri;
frame.sandbox = "allow-scripts allow-same-origin";
frame.style = `display:none`;
frame.onload = (e) => {
// 向 iframe 發送一個消息,請求檢查 cookie 的情況
frame.contentWindow.postMessage(JSON.stringify({ 'test': 'cookie' }), '*');
};
document.body.appendChild(frame);
};
export default cookieTest;
你可以直接把上面的代碼片段放入你的網站中,並提供一個回調函數來爲用戶呈現適當的消息。
現在,我們可以成功地在運行時檢測到用戶的第三方 Cookie
是否已啓用了!
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/OjpzmJDII1jy3ZSuc6eOGA