浏览器指纹跨域共享

2,365 阅读2分钟
原文链接: segmentfault.com
概念:设备id 即设备指纹,用来表示用户设备的唯一性

背景

最近在做用户行为分析项目的开发,需要采集用户的设备信息,需要用设备指纹来唯一表示用户操作设备。web 存储都和浏览器相关,我们无法通过js 来标识一台电脑,只能以浏览器作为设备维度来采集设备信息。即用户电脑中一个浏览器就是一个设备。

问题

web 变量存储,我们第一时间想到的就是 cookie,sessionStorage,localStorage,但是这3种存储方式都和访问资源的域名相关。我们总不能每次访问一个网站就新建一个设备指纹吧,所以我们需要通过一个方法来跨域共享设备指纹

方法

我们想到的方案是,通过嵌套 iframe 加载一个静态页面,在 iframe 上加载的域名上存储设备id,通过跨域共享变量获取设备id,共享变量的原理是采用了iframe 的 contentWindow通讯,通过 postMessage 获取事件状态,调用封装好的回调函数进行数据处理

实现

SDK 采集端,调用方初始化的时候调用方法

collect.setIframe = function () {
      var that = this
      var iframe = document.createElement('iframe')
      iframe.src = "http://localhost:82/"
      iframe.style = 'display:none'
      document.body.appendChild(iframe)
      iframe.onload = function () {
        iframe.contentWindow.postMessage('loaded','*');
      }

      //监听message事件
      window.addEventListener("message", function(){
            that.deviceId = event.data.deviceId

            console.log('获取设备id',that.deviceId)

            sessionStorage.setItem('PageSessionID',helper.upid())
            helper.send(that.getParames(), that.eventUrl);
            helper.sendDevice(that.getDevice(), that.deviceUrl);
      }, false);
}

嵌套在 iframe 静态页面里的脚本

   <script>

        var getDeviceId = function() {
                return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
                        return v.toString(16);
                });
        };

        var hasCreated = false
        var _deviceId = ''
        if(document.cookie){
                document.cookie.split(';').forEach(function(i){
                        if(i.indexOf('deviceId')>-1){
                                hasCreated = true
                                _deviceId = i.split('=')[1]
                        }
                })
        }

        if(!_deviceId && (sessionStorage.getItem('deviceId')||localStorage.getItem('deviceId'))){
                hasCreated = true
                _deviceId = sessionStorage.getItem('deviceId')||localStorage.getItem('deviceId')
        }


        if(!hasCreated) {
                _deviceId =  getDeviceId()
                document.cookie = 'deviceId=' + _deviceId
                sessionStorage.setItem('deviceId',_deviceId)
                localStorage.setItem('deviceId',_deviceId)
        }

        //回调函数
        function receiveMessageFromIndex ( event ) {
                console.log( 'receiveMessageFromIndex', event )
                parent.postMessage( {deviceId: _deviceId}, '*');
        }
        //监听message事件
        window.addEventListener("message", receiveMessageFromIndex, false);

    </script>

扩展阅读

跨浏览器cookie
跨浏览器指纹识别
浏览器指纹追踪
使用postMessage解决iframe跨域通信问题
window.postMessage