美文网首页
Canvas帆布指纹识别技术和 Fingerprinting的使

Canvas帆布指纹识别技术和 Fingerprinting的使

作者: 忘了呼吸的那只猫 | 来源:发表于2021-04-06 09:16 被阅读0次

    在过去,实现上述 Cookie 是最受欢迎的一种。但由于移动互联网的发展,移动设备限制、用户禁用 Cookie。使得 Cookie 愈来愈不受待见。 伴随着 HTML5 的成熟,通过 Canvasfingerprintjs 技术标识一个唯一的浏览器逐渐被接受。它的特点是不通过 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

    相关文章

      网友评论

          本文标题:Canvas帆布指纹识别技术和 Fingerprinting的使

          本文链接:https://www.haomeiwen.com/subject/gqlqkltx.html