【HTML5】新一代的用户唯一性识别思路

做过 web 应用的童鞋应该都经历过,在很多时候,我们需要在用户没有登录的情况下也能识别用户唯一性,以前一般都用 ip + cookie 来追踪。但是呢,在现在用户越来越重视隐私、用户对 web 技术越来越了解的情况下,这种方式已经越来越不可靠了。

传统识别技术的缺陷

 传统技术的缺陷在于,对于用户的识别是被动的,IP 并不是用户的唯一身份,因为 IPv4 资源的紧缺性、运营商策略问题,用户分配到的 IP 地址并不固定,甚至如果是 NAT 构建的局域网,所有用户对外的公网 IP 都是一样的,服务器根本不知道发起请求的用户是不是同一个。

基于上述问题,又衍生出了 IP + Cookie 的识别方式,既然用户没有唯一身份识别,那就构造一个,将这个唯一识别放置到 cookie 中,这样用户访问时,客户端会自动携带上。

上述方案在一般场景下都没什么问题,但是仍存在一个无法解决的问题,就是这个“唯一身份”的生成并没有跟用户产生任何关联。也就是说,如果用户清空了cookie,再次访问,服务器会将其识别成一个新的用户。

基于硬件的识别方案

因为传统方案的先天缺陷,所以我们要想尽办法将这个唯一身份跟用户进行强绑定,而 HTML5 标准里推出的关于多媒体的 API 让这个设想成为了可能。

像 Canvas、Audio、Video 都提供了用户生成媒体的 API,也就是用户可以自己生成图片、音频、视频。不知道大家有没有关注过,其实这些媒体的生成都跟硬件相关的!

举例来说,用 canvas 画一个 20px 长、10px 宽的矩形,填充红色,生成图片其实是完全不一样的!这里的不一样不是指我们看到的图像不一样,而是这个图片的二进制数据存在不一样!而在同一个环境下,你就算生成相同图片一百次,得到的图片都是每个字节都是一样的,这算是硬件指纹吧。

利用这个特性,我们可以用于生成用户唯一识别码,因为用户就算可以隐藏他的 IP、浏览器信息,但是他的硬件无法更改。

下面是演示代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Canvas Fingers</title>
</head>

<body>
    <p id="ret"></p>
    <script>
        function getUUID() {
            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');
            context.strokeStyle = 'red';
            context.moveTo(100, 200);
            context.lineTo(300, 450);

            return canvas.toDataURL().toString().replace('data:image/png;base64,', '')
        }
        document.querySelector('#ret').innerText = getUUID();
    </script>
</body>

</html>

总结

上面就是基于用户硬件做唯一识别的思路,唯一的短板可能就是浏览器必须要支持 canvas 和启用 javascript 了,不过现在这个时代下,没人会关闭这些选项吧。

同理,除了 canvas,我们还可以利用 Audio、Video 的相关 API 接口实现相同的效果,原理就是它们都是基于硬件进行多媒体生成的,具体实现就留给大家自行实现吧。