如何检测页面是否允许访问Cookie
1. 检测API
书接上文,如果浏览器设置了禁止访问cookies,将导致如 无法访问localStorage 等异常报错。这类错误是由用户的浏览器设置导致的,如果开发者没有拿到出问题的现场及相关日志,是比较难排查的。那么有没有方法可以在代码里检查页面是否允许访问cookies呢?
答案肯定是有的,浏览器为我们开发者提供了一个贴心的api:Navigator.cookieEnabled。这是一个只读属性,返回一个布尔值,来表示当前页面是否启用了 cookie。这个属性已经被主流浏览器实现了(除了IE这个奇葩,不过现在微软也放弃他了),所以可以放心大胆地用。
2. 如何检测
cookie可以分为两大类,一个是本地cookie,一个是第三方cookie。下面将分别介绍他们的检测方案:
2.1 本地cookie
本地cookie最简单,navigator里面存储的就是当前页面的状态和标识,所以直接读取即可。
if (!navigator.cookieEnabled) {
// 浏览器不支持 cookie,或者用户禁用了 cookie。
}
2.2 第三方cookie
第三方cookie的一般形式是通过iframe加载第三方网站的时候,iframe内部的cookie即为第三方cookie。第三方网站的内容一般是跨域的,无法访问到其内容,也无法进行修改,因而无法直接使用上面的方法读取其内部的cookie访问状态。
我们换个思路,其实不一定需要主页面“主动”获取第三方网站的cookie访问状态,也可以由第三方网站自行检测cookie访问状态后“通知”父页面。而且对于浏览器来说,只要是非同源的网站,都是可以认为是第三方的。那我们可以自行构建一个能够自行检测cookie状态的第三方网站,然后将cookie访问状态通过postMessage回传给父页面就可以了。
自建第三方网站
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
window.onload = () => {
window.parent.postMessage(JSON.stringify({ cookieEnabled: navigator.cookieEnabled }), '*');
}
</script>
</body>
</html>
主页面
export const CookieDetector = (callback: (data: any) => void) => {
let ifrm: any = document.createElement('iframe');
const timeout = setTimeout(() => {
window.removeEventListener('message', test);
ifrm.remove();
ifrm = null;
callback(true);
}, 1000);
const test = (data: any) => {
clearTimeout(timeout);
try {
const jsonData = JSON.parse(data);
window.removeEventListener('message', test);
ifrm.remove();
ifrm = null;
callback(jsonData.cookieEnabled);
} catch (e) {
// do nothing
}
};
window.addEventListener('message', (event: any) => test(event.data));
document.body.appendChild(ifrm);
ifrm.onload = () => {
clearTimeout(timeout);
};
ifrm.src = ''; // 自建第三方网站地址
};