在过去,实现上述 Cookie
是最受欢迎的一种。但由于移动互联网的发展,移动设备限制、用户禁用 Cookie
。使得 Cookie
愈来愈不受待见。 伴随着 HTML5
的成熟,通过 Canvas
和fingerprintjs
技术标识一个唯一的浏览器逐渐被接受。它的特点是不通过 Cookie
,用户基本无法屏蔽它 。
不废话上代码:
<html>
<body>
<div id="myCanvas"></div>
</body>
<script>
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var txt = 'http://security.tencent.com/';
ctx.textBaseline = "top";
ctx.font = "14px 'Arial'";
ctx.textBaseline = "tencent";
ctx.fillStyle = "#f60";
ctx.fillRect(125,1,62,20);
ctx.fillStyle = "#069";
ctx.fillText(txt, 2, 15);
ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
ctx.fillText(txt, 4, 17);
var d=document.getElementById("myCanvas");
d.appendChild(canvas)
var b64 = canvas.toDataURL().replace("data:image/png;base64,","");
var bin = atob(b64);
console.log(bin)
var crc = bin2hex(bin.slice(-16,-12));
console.log(crc);
// 输出crc码,crc在一定程度上标识了浏览器的唯一性,但是,在相同设备,
// 相同浏览器上,重复特别严重。(该指纹能够识别出了某种GPU在安装了某种字体下的群体。)
function bin2hex(str) {
var result = "";
for (i = 0; i < str.length; i++ ) {
var c = str.charCodeAt(i);
result += byte2Hex(c>>8 & 0xff); // 高字节
result += byte2Hex(c & 0xff);// 低字节
}
return result;
}
function byte2Hex(b) {
if(b < 0x10)
return "0" + b.toString(16);
else
return b.toString(16);
}
</script>
</html>
其实现原理:
获取绘画的内容,需要使用到 canvas.toDataURL()
方法,该方法返回的是图片内容的 base64
编码字符串。对于 PNG
文件格式,以块 chunk
划分,最后一块是一段 32
位的 CRC
校验,提取这段 CRC
校验码便可以用于用户的唯一标识,通过验证,CRC
在一定程度上标识了浏览器的唯一性,
缺陷:在相同设备,相同浏览器上,重复特别严重。
国外有一个经过优化后的表示浏览器的唯一性的 JavaScript 库,fingerprintJS 。
-
1.它除了利用 Canvas 以外,还加入了其它的影响因素,这些因素包括
-
2.浏览器http请求中的用户代理-
navigator.userAgent
-
3.浏览器的语言(中文、英文……)-
navigator.language
-
4.设备屏幕的色彩信息-
screen.colorDepth
-
5.设备屏幕的宽高-
screen.height screen.width
-
6.格林威治时间和本地时间之间的时差-
Date().getTimezoneOffset()
-
7.是否支持
sessionStorage-window.sessionStorage
-
8.是否支持
localStorage-window.localStorage
-
9.是否支持
indexdDB-window.indexedDB
-
10.是否支持-
docment.body.addBehavior
(IE5的一个属性) -
11.是否支持调用本地数据库-
window.openDatabase
-
12.浏览器所在系统的CPU等级-
navigator.cupClass
-
13.客户端的操作系统-
navigator.platform
-
14.是否支持Do not track功能-
navigator.doNotTrack
-
15.获取浏览器部分插件信息-
flash plugin、Adobe PDF reader、QuickTime、real players、ShockWave player、Windows media player、Silverlight、Skype
-
16.
Canvas
指纹
据说该标识精准度达90%以上
实现源码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Fingerprint2 TEST</title>
<style>
body {
color: #555;
}
#info {
font-size: 12px;
}
#control span {
color: #333;
margin-left: 10px;
}
</style>
</head>
<body>
<div id="info">
<p>Fingerprint2 Github: <a href="https://github.com/Valve/fingerprintjs2" target="_blank">https://github.com/Valve/fingerprintjs2</a>
</p>
<p>纯前端实现的浏览器指纹采集器,通过获取浏览器中所有能获取到的信息(部分通过base64转成String),最后生成出md5,用于该用户在该设备上的唯一标识码,官方宣称准确度高达99.5%</p>
</div>
<div id="control">
<button onclick="start()">开始</button>
<span>userAgent:</span><input type="checkbox" id="userAgent" checked="checked">
<span>fonts:</span><input type="checkbox" id="fonts" checked="checked">
<span>fontsFlash:</span><input type="checkbox" id="fontsFlash" checked="checked">
<span>canvas:</span><input type="checkbox" id="canvas" checked="checked">
<span>webgl:</span><input type="checkbox" id="webgl" checked="checked">
<span>audio:</span><input type="checkbox" id="audio" checked="checked">
<span>enumerateDevices:</span><input type="checkbox" id="enumerateDevices" checked="checked">
</div>
<div id="view">
</div>
<script src="https://cdn.staticfile.org/fingerprintjs2/2.1.0/fingerprint2.min.js"></script>
<script>
function start() {
const start = new Date().getTime();
let view = document.querySelector('#view');
view.innerHTML = '';
let excludes = {};
if (!document.querySelector('#userAgent').checked) {
excludes.userAgent = true;
}
if (!document.querySelector('#audio').checked) {
excludes.audio = true;
}
if (!document.querySelector('#enumerateDevices').checked) {
excludes.enumerateDevices = true;
}
if (!document.querySelector('#fonts').checked) {
excludes.fonts = true;
}
if (!document.querySelector('#fontsFlash').checked) {
excludes.fontsFlash = true;
}
if (!document.querySelector('#webgl').checked) {
excludes.webgl = true;
}
if (!document.querySelector('#canvas').checked) {
excludes.canvas = true;
}
let options = {excludes: excludes}
Fingerprint2.get(options, function (components) {
// 参数
const values = components.map(function (component) {
return component.value
});
// 指纹
console.log(values.join(''))
const murmur = Fingerprint2.x64hash128(values.join(''), 31);
view.innerHTML += '<p>指纹 : ' + murmur + '</p>';
view.innerHTML += '<p>消耗 : ' + (new Date().getTime() - start) + ' 毫秒</p>';
view.innerHTML += '<p>使用的参数 : </p>';
for (const c of components) {
view.innerHTML += '<p>' + c.key + ' : ' + c.value + '</p>';
}
});
}
</script>
</body>
</html>
总结:
Canvas
指纹只能作为一参考属性去判断设备的唯一性,不能只用这一个因素来判定设备唯一性。FingerPrint.js
也不能取代 Cookie
,但是可以作为辅助,如果用户清除了 Cookie
的情况下,还可以通过 FingerPrint.js
跟踪到该用户重新 Set Cookie
网友评论