canvas指纹

使用背景:

在一些业务中我们需要获取一些匿名用户的基本信息,以此来对用户的行为进行分析,然后针对一定的用户群体进行定向推荐。用户信息采集一个重要的原则是要对用户的行为进行保密(不能把采集的信息进行明文存储,一个思路是前端只存储一个hasid具体的信息存在数据库里面)

基本思路:

1:生成一个识别唯一设备的标识码

理想情况下是一个用户对应一个识别码,然而现实中我们可能最多做到一个浏览器对应一个用户连一个设备对应一个用户都做不到(不要问我为什么,前端能获取的信息就那点,也没有权限获取用户的硬件信息)。当用户懂得技术的话把本地缓存和cookie一清我们连一个浏览器对应一个用户都做不到了,考虑实际情况,大部分用户都不会去刻意的清缓存的,因此我们这工作还是有价值的,能够覆盖80%以上 的情况就是有价值的,那么我们如何生成这个唯一设备码hashid呢?

  • 时间戳+随机数

万能生成唯一码的方法,这种方法几乎不可能出现重复(除非平行时空的另一个你此时也在访问同一个页面)

var code=new Date().getTime()+Math.radom()

return hex_md5(code);//生成的唯一码进行md5就是我们需要的设备号了

啊,什么是md5?

  • canvas指纹

本文的重头戏,canvas指纹登场了做个简单介绍吧:

每一种浏览器都会使用不同的图像处理引擎,不同的导出选项,不同的压缩等级,所以每一台电脑绘制出的图形都会有些许不同,这些图案可以被用来给用户设备分配特定编号(指纹),也就是说可以用来识别不同用户,一般情况下用户不会去更换硬件设备,所以canvas可以很好的指定当前用户的浏览器,但是当多个用户的硬件设备,浏览器一致时就特别容易产生相同的指纹,所以canvas指纹并不能完全的替代cookie作为用户的身份验证,但是可以作为辅助的验证信息。

识别范围:浏览器

用途:辅助用户验证消息

缺点:原始的实现的方法在同一硬件设备同一浏览器容易重复

原始实现方法:

var canvas = document.createElement('canvas');

var ctx = canvas.getContext("2d");

ctx.font = "24px Arial";

ctx.fillText("carnoc",22,33);

ctx.moveTo(0,0);

ctx.lineTo(100,100);

ctx.stroke();

var b64 = canvas.toDataURL().replace("data:image/png;base64,","");

return hex_md5(b64)//这里又md5啦,md5后的识别码就是我们需要的唯一设备号

 

通过定义相同的canvas行为产生一个base64的数据,但是由于base64的数据不好存储这里使用js-md5进行编码

问题:这样简易的canvas指纹在相同设备相同浏览器中重复率极高,所以要综合其他因素进行判断这里有一个改进版的库,里面的判断因素包括:

  1. 浏览器http请求中的用户代理-navigator.userAgent
  2. 浏览器的语言(中文、英文……)-navigator.language
  3. 设备屏幕的色彩信息-screen.colorDepth
  4. 设备屏幕的宽高-screen.height screen.width
  5. 格林威治时间和本地时间之间的时差-Date().getTimezoneOffset()
  6. 是否支持sessionStorage-window.sessionStorage
  7. 是否支持localStorage-window.localStorage
  8. 是否支持indexdDB-window.indexedDB
  9. 是否支持-docment.body.addBehavior(IE5的一个属性)
  10. 是否支持调用本地数据库-window.openDatabase
  11. 浏览器所在系统的CPU等级-navigator.cupClass
  12. 客户端的操作系统-navigator.platform
  13. 是否支持Do not track功能-navigator.doNotTrack
  14. 获取浏览器部分插件信息-flash plugin、Adobe PDF reader、QuickTime、real players、ShockWave player、Windows media player、Silverlight、Skype
  15. canvas指纹

网传的测试结果:

1.由于涉及设备以及浏览器的判定因素非常多,重复性很低,31台设备皆无重复

但是可以设想,毕竟是通过各种属性值去判断唯一性,理想情况下如果两台设备相同浏览器各种设置也相同,还是会出现重复

2.也正因为涉及的因素多,一旦设备系统更新 or 浏览器版本更新 or 浏览器关键插件有变化(版本更新 or 新增卸载关键插件) ,生成的ID都会改变,由于浏览器版本更新还是比较频繁的,很容易失去之前跟踪的用户

参考资料:https://www.freebuf.com/news/40745.html

 

我的测试代码:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fingerprintjs2/1.5.1/fingerprint2.min.js"></script>

new Fingerprint2().get(function(result, components){

resolve(hex_md5(result))

});

是一个异步的API,res里面传回得到的canvas指纹,改进版的唯一性得到大大的提高(亲测的)

结论:

canvas指纹只能作为一参考属性去判断设备的唯一性,不能只用这一个因素来判定设备唯一性。fingerPrint.js也不能取代cookie,但是可以作为辅助,如果用户清除了cookie的情况下,还可以通过fingerPrint.js跟踪到该用户重新set cookie

 

2:存储设备码

第一步的用户的唯一设备号已经有了那么我们如何进行安全永久(脆弱)的保存呢?

我使用的是cookie+localStorage进行保存的

cookie有一个好处,是可以在二级域名下共享cookie的如m.baidu.com和news.baidu.com,而本地缓存则做不到这样就顺便解决了同二级域名共享一个设备号的需求。

主要思路:

  • 获取的设备号存cookie,同时存本地缓存localStorage
  • 若检查到本地缓存的设备号与cookie不一致,以cookie为准,同时更新本地缓存并把更改信息提交至后台
  • 每次进行访问时检查cookie和本地缓存有一个被清除了就使用另一个的设备号进行恢复
  • 本地和cookie都没有的话只能重新生成一个设备号进行存储了(我也很绝望啊)

3:收集信息且提交

经过第二步我们知道了如何生成设备号和存储设备号了那么就应该进入第三步收集信息的环节了

具体要收集哪些信息看你的需求了(反正能得到的信息本来也不多)r如:设备分辨率,地理信息(移动端且开了GPS),浏览的网页url,浏览时间等等,最后将你得到和信息和设备号hashid传到后台吧

 

 

总结:要进行一次匿名用户信息一般需要三部

1:生成唯一设备码

2:收集信息

3:存储提交

如果以上的三步有更好的实现方法,欢迎讨论分享。菜鸟一枚,出错之处望指出,不胜感谢。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章