哈喽,大家好 我是
xy
👨🏻💻. 作为一名前端开发工程师,应该都用过H5
中的canvas
吧!!! 但是你真的了解它吗?Canvas '指纹识别'
技术又是什么? 本文将由浅入深,带你了解Canvas '指纹识别'
技术
什么是 Canvas
Canvas
API(画布)是在HTML5
中新增的标签用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作
的位图(bitmap)。
Canvas
对象表示一个 HTML 画布元素 <canvas></canvas>
。它没有自己的行为,但是定义了一个 API 支持脚本化客户端绘图操作。
Canvas 能做什么
- 基础图形的绘制
- 文字的绘制
- 图形的变形和图片的合成
- 图片和视频的处理
- 动画的实现
- 小游戏的制作
随着互联网的发展,用户对页面的视觉
和交互
有着更高的要求,传统的 web 前端开发无法得到满足,所以利用强大的Canvas绘图能力
,可以是网页显示的内容更加的丰富多彩,Canvas 在给用户带来更好的视觉和交互上的体验。
随手绘制一个简单的图形
<!-- html -->
<body>
<canvas
id="canvas_xy"
width="500"
height="400"
style="box-shadow: 0 0 20px black"
>
当前浏览器不支持 canvas
</canvas>
</body>
<!-- js -->
<script type="text/javascript">
// 获取 canvas 元素对应的 DOM 对象
var canvas_xy = document.getElementById("canvas_xy");
// 获取在 canvas 上绘图的 canvasRenderingContent2D 对象
var ctx = canvas_xy.getContext("2d");
//设置绘制起点
ctx.moveTo(100, 100);
//设置绘制下一个点
ctx.lineTo(200, 200);
//设置绘制下一个点
ctx.lineTo(400, 100);
//结束绘制
ctx.closePath();
//设置线的宽度
ctx.lineWidth = 10;
//设置绘制的样式
ctx.strokeStyle = "red";
//绘制点之间的线路
ctx.stroke();
// 设置填充样式
ctx.fillStyle = "green";
// 填充当前视图
ctx.fill();
</script>
效果如下:
已经了解了 Canvas 的基本使用的同学肯定会问,它和指纹识别
有什么关系呢? 其实这里说的指纹识别并不是真正的指纹识别技术
,而是利用了Canvas
在不同操作系统、不同浏览器上,产生的图片内容不完全相同(我们肉眼是无法区分的)来标识用户。
既然提到 Canvas 指纹
,那肯定也会想到浏览器指纹
了,这两种有什么区别和关联呢?
别急!!! 一起来看看浏览器指纹
和Canvas指纹
浏览器指纹
一般情况下,网站或者广告商都想要一种技术可以在网络上精确的定位到每一个个体,这样就可以通过收集这些个体的数据,然后加以分析之后更加精确的去推送广告和其他的一些活动。Cookie
技术是非常受欢迎的一种。当用户访问一个网站时,网站可以在用户当前的浏览器 Cookie
中永久植入一个含有唯一标示符(UUID
)的信息,并通过这个信息将用户所有行为
(浏览了哪些页面?搜索了哪些关键字?对什么感兴趣?点了哪些按钮?用了哪些功能?看了哪些商品?把哪些放入了购物车等等)关联起来。
而随着网民对个人隐私的重视,Cookie
越来越不受待见。不少安全工具甚至是浏览器都开始允许或引导用户关闭 Cookie
功能,比如很多主流浏览器都有一个“隐私模式浏览”
功能。同时,我们可以很方便的使用浏览器的快捷键清除缓存,这样在两次访问的区间也就无法识别是否是同一个用户,这样一来,网站就很难追踪用户行为了。
这个时候浏览器指纹
也就应运而生。
如何获取浏览器指纹?
想必大家一定知道浏览器 navigator 对象
吧,通过 navigator
对象我们可以获取到足够的浏览器相关的信息。我们可以直接在浏览器控制台输入 navigator
: 输出如下:
其中获取的硬件类型
、操作系统
、用户代理
、系统字体
、语言
、屏幕分辨率
、浏览器插件
、浏览器扩展
、浏览器设置
、时区差
、地理位置
等众多信息,这些信息可以称之为浏览器的指纹信息
。
这些指纹信息“类似”
人类的身高、年龄
等,有很大的冲突概率,只能作为辅助识别。
这些指纹不能对某个人进行唯一性
标识,也无法对客户端进行唯一性
判定,基于HTML5
的诸多高级指纹
对此提供了新思路。
HTML5
的高级指纹
: Canvas 指纹:
什么是 Canvas 指纹
从根本上来说,每一种浏览器都会使用不同
的图像处理引擎
,不同的导出选项
,不同的压缩等级
,所以每一台电脑绘制出的图形都会有些许不同,这些图案可以被用来给用户设备分配特定编号
(指纹
),也就是说可以用来识别不同用户。
那么,如何给我们的网站增加 Canvas指纹
呢?
我们可以通过html5
的canvas
接口,在网页上绘制一个隐藏
的画布图像。
值得注意的是,如果用户的设备
,操作系统
,浏览器
都一样的话,计算出来的 canvas 指纹是一样
的。换句话说:canvas
指纹不具备唯一性
,要和其他的浏览器指纹相互结合利用来进一步计算出区分度更高的指纹标识。
如何获取 Canvas 指纹
基于 Canvas
绘制特定内容的图片,使用canvas.toDataURL()
方法返回该图片内容的base64编码
字符串。对于 PNG 文件格式,以块(chunk)划分,最后一块是一段32位的CRC校验
,提取这段CRC校验码
便可以用于用户的唯一标识
。
测试结果表明,同一浏览器
访问该域时生成的CRC校验码
总是不变
。
可以简单理解为同样的HTML Canvas
元素绘制操作,在不同的操作系统不同的浏览器上,产生的图片内容其实是不完全相同的。出现这种情况可能是有几个原因:
- 在图片格式上,不同 web 浏览器使用了不同的图形处理引擎、不同的图片导出选项、不同的默认压缩级别等。
- 在像素级别来看,操作系统各自使用了不同的设置和算法来进行抗锯齿和像素渲染操作。
- 即使是相同的绘图操作,最终产生的图片数据在 hash 层面上依然是不同的。
获取 Canvas 指纹:
<script type="text/javascript">
function bin2hex(s) {
var i,
l,
o = "",
n;
s += "";
for (i = 0, l = s.length; i < l; i++) {
n = s.charCodeAt(i).toString(16);
o += n.length < 2 ? "0" + n : n;
}
return o;
}
function getUUID(domain) {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var txt = domain;
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 b64 = canvas.toDataURL().replace("data:image/png;base64,", "");
// window.atob 用于解码使用 base-64 编码的字符串
var bin = atob(b64);
var crc = bin2hex(bin.slice(-16, -12));
return crc;
}
console.log(getUUID("公众号:前端开发爱好者"));
</script>
不同浏览器
查看获得不同的指纹信息:
如何检测 canvas 指纹?
在线检测地址:https://browserleaks.com/canvas
如何隐藏自己的 canvas 指纹?
随着谷歌浏览器宣布为了保护用户的隐私,跨域请求不再携带cookies
。浏览器指纹技术成为追踪用户的热门技术,那有没有办法隐藏
我们的 canvas 指纹呢?
目前主要用2
种方式:
- 安装浏览器插件,谷歌应用商店有随机修改
canvas
指纹的插件(CanvasFingerprintBlock
),其原理是,每次随机往 canvas 画布里面注入一个随机的噪音
(人肉眼是看不到的),从而影响图片数据的CRC
校验结果。 - 类似
LoginBox
,multilogin
这样的指纹仿关联软件,其原理是:为每个浏览器窗口环境单独分配指纹数据,和第 1 种方式一样,也是往 canvas 画布里面注入一个随机的噪音,只是这个噪音是固定的。