追踪用户?只知道cookie可不够

3,797 阅读5分钟

背景

出于这样或那样的目的,我们需要精准的标识每一个用户,进一步了解他们的用户行为(浏览了哪些内容?搜索了哪些关键字?点击了哪些按钮?在哪里停留的时间长?等等),甚至是将用户的不同站点数据关联起来,然后给用户提供更加精准、个性化的信息流。其实好多巨头早在很久之前就开始做这些工作了,比如某度

作为可以准确标识用户身份的方案,需要满足但不限于以下的条件:

  • 唯一性:每个用户的身份标识都应该是唯一的,区别于其他用户的
  • 稳定性:保证在特定的时间、条件下,用户的身份标识保持不变
  • 维度大:需要在面对海量用户时,依然可以产生唯一的身份标识

下面来分享一下我所了解到的,可以标识用户身份的方案(递进关系):

1. 方案一 cookie:

这个是我最先接触到的方式,也是最常见的方式。至于怎么操作cookie,相信大家都能运用自如了,如果有疑问可以参看 这里

当用户访问网站时,你可以创建一个名为userId的cookie,用js生成一个32+的唯一值作为它的值,使用这对值来标识用户,关联用户行为,举个🌰:

const createCookie = (name, value, days, domain, cpath) => {
  let path = cpath || '', expires = "", cookieURL = '; path=' + path + '/';
  if (!!days) {
    let date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    expires = "; expires=" + date.toUTCString();
  }
  if (!!domain) {
    cookieURL = cookieURL + '; domain=' + domain
  }
  document.cookie = name + "=" + value + expires + cookieURL;
}
const s4 = () => {
    return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
}

let userId = s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
createCookie('userId',userId,3650)

以后就可以使用userId来实现用户追踪,方便后续的数据分析。建议将过期时间设置的大一点,以便持久分析跟踪用户行为。但是随着互联网的发展,设备的限制、用户隐私意识的提高,很多时候cookie会被禁用,所以这种方式显得不是那么稳了。我们急需一种替代方案的出现

2. 方案二 canvas

随着h5规范的推进,越来越多的浏览器支持 canvas 标签,使得我们可以利用它创造出一种新的用户追踪方案。 但是why?how?

先说这种方案的原理:

  • 浏览器不同、内核不同,绘制出来的图片各不相同且唯一
  • 不同的操作系统使用了不同的设置和算法来进行像素渲染操作

主要利用这些差异来区分不同用户

再说一下具体做法

使用的是 canvas 的一个神奇方法----toDataURL([type, encoderOptions])。这个方法返回绘画内容的data URL(base 64形式),我们可以利用这个返回值,截取作为CRC校验的最后32位来作为用户的唯一标识。

在了解了以上信息之后,我们来举个🌰:

const binToHex = (str) => {
	let o = ''
	if(!str) return
	for(let i = 0,len = str.length;i<len;i++){
		 let n = str.charCodeAt(i).toString(16);
         o += n.length < 2 ? '0' + n : n;
	}
	return o
}
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d')
//圆形
ctx.beginPath();
ctx.arc(100,75,50,0*Math.PI,2*Math.PI)
ctx.stroke()
//文字
let message = "I'm a canvas"
ctx.font = '18px'
ctx.fillStyle = "#068";
ctx.fillText(message, 10, 20);
let base64Str = canvas.toDataURL().replace("data:image/png;base64,","");
let bin = atob(base64Str);
let crc = binToHex(bin.slice(-16,-12));
console.log(crc)

同一个浏览器隐身,正常两种模式运行结果

对照一下cookie方案,总结一下canvas方案的优缺点

优点

  • html5 canvas技术被所有主流浏览器支持,可以在PC、平板、手机上使用
  • 基本上是无法屏蔽的

缺点:

  • 用于是无法屏蔽的,所以你的行为相当于公开的
  • canvas方案跟设备、系统、浏览器有很大的相关性。唯一性不能保证而且会随着系统、浏览器更新而变化,暂且算个方案吧 (关于它的唯一性问题,您可以通过使用相近的系统版本、浏览器版本去验证)

基于缺点,canvas指纹只能作为判断用户唯一性的参考。不能完全满足我们的需求。

3.方案三:Fingerprintjs

为了表示尊敬,这里先贴出Fingerprintjs github。 它是一个纯用javascript、没有依赖关系的浏览器指纹库,压缩之后只有1.2k,准确率达到94%。它通过收集用户ua、屏幕数据、语言、插件、时区、canvas指纹等数据生成一个用户标识追踪用户(默认使用 Murmur Hash 算法返回一个32位整数)

上代码截图直观呈现收集的数据

优点

  • 包含多种因素,重复率很低

缺点

  • 正是因为包含的因素很多,用户的一些行为就可以改变标识,很容易失去之前跟踪的用户(例如:插件卸载、安装,系统升级等都可能会影响)

貌似还是不能满足日益增长的需求啊

4.方案四:Fingerprintjs2

Fingerprintjs2 github ,这个是FingerprintJS的升级版。Fingerprintjs是在2012年开发的,现在无法在不降低兼容性的情况下对其进行改进,所以有了Fingerprintjs2。

这个项目收集了更多的数据,并且所有数据都是可配置的,你可以仅挑选需要的选项或者全部启用它们,而且还特别贴心的“照顾”了IE,QQ,百度等NB浏览器

来看看它所收集的数据吧,真是多啊

由于是二代产物,缺点已经很少了。再结合cookie绝对是无敌的存在。

讲了这么多,总觉得很遥远,来一个已经开始使用这项技术的网站----火币。 看看它的请求,除了token还带了什么你就知道了

好了,这就是我关于用户追踪的看法,希望可以帮到你

未经本人允许,不得转载。文章有疏漏浅薄之处,请各位大神斧正