FingerprintJS 添加请求指纹

1,768 阅读3分钟

简介

FingerprintJS是一个开源的、客户端的浏览器指纹库,它查询浏览器属性,并从这些属性中计算出一个散列的访问者标识符。与cookie和本地存储不同,在隐身/私密模式下,甚至当浏览器数据被清除时,指纹仍然保持不变

它允许你快速获取到一个浏览器的指纹。它通过收集各种浏览器和设备的信息来生成一个相对唯一的ID。它比简单的用户代理字符串检测更加可靠精确

它提供一种更加精确、可靠且对用户相对透明的方式,来识别和跟踪用户,特别是在网络安全、欺诈检测、在线广告和个性化内容展示等领域具有广泛的应用。

背景

如何在没有明确用户登录信息的情况下,识别和跟踪用户或设备。

传统的识别方法,如基于IP地址或者Cookies的跟踪,存在一些明显的局限性和缺点:

  1. IP地址:用户的IP地址可能会变化(比如通过移动网络或VPN),并且很多用户可能共享同一个IP地址(如在同一个家庭或办公室网络中)。

  2. Cookies:用户可以清除Cookies,或者使用隐私模式浏览来避免跟踪。此外,一些浏览器和隐私工具现在默认阻止或限制Cookies的使用。

方案

  通过FingerprintJS 第三方库,获取客户端唯一指纹,在发送请求时请求头带上该指纹做为标识。

项目中使用

通过npm安装

npm install @fingerprintjs/fingerprintjs

代码中获取设备指纹:

// 异步加载FingerprintJS
(async () => {
  // 加载FingerprintJS模块
  const FP = await import('@fingerprintjs/fingerprintjs');

  // 初始化FingerprintJS
  const fp = await FP.load();

  // 获取访问者的指纹
  const result = await fp.get();

  // result.visitorId即为用户的唯一指纹  可以将visitorId用作后续请求的标识等
  window.localStorage.setItem("visitorId", result.visitorId);
})();

暂时无法在飞书文档外展示此内容

在main.ts 中引入:

import "xxx/fingerPrint";

在请求拦截器添加请求头:

config.headers["browser_uuid"] = window.localStorage.getItem("visitorId");

相关文档

Github:

github.com/fingerprint…

官网:

fingerprint.com/

疑问点

  1. id变化的时机了解

浏览器无痕模式不会影响id计算

基本只有在浏览器修改、版本变更、时区等

可能会出现不同的用户,browserId相同的情况

  1. 版本与收费
版本收费准确度文档
v4用于生产收费fingerprint.com/blog/finger…
v3开源 github.com/fingerprint…50%github.com/fingerprint…
  1. 无法覆盖面
  • baseconfig不接入:baseconfig的时机早于browserId

  • 神策买点需要接入:埋点接口如要接入browserId,需额外配置

  • 华为云APM不需要接入

  • 其他未统一使用axios的请求不需要接入

  1. 浏览器兼容
  • Edge 105+
  • Chrome 57+
  • Firefox 67+
  • Desktop Safari 12.1+
  • Mobile Safari 11.0+
  • Samsung Internet 14.0+
(() => {
  const ITEM_KEY = 'browserId';
  const CDN_URL = 'https://js.hlestudy.com';
  const BUCKET_URL = '/frontend-solutions/fingerprint/v1.0.0/fp.min.js';
  const FP_URL = CDN_URL + BUCKET_URL;
  try {
    if (!localStorage.getItem(ITEM_KEY)) {
      const s = document.createElement('script');
      s.onload = function () {
        if (FingerprintJS) {
          const fpPromise = FingerprintJS.load({ monitoring: false });
          fpPromise
            .then((fp) => fp.get())
            .then((result) => {
              console.log(result);
              localStorage.setItem(ITEM_KEY, result.visitorId);
            });
        }
      };
      s.src = FP_URL;
      const f = document.getElementsByTagName('script')[0];
      f.parentNode.insertBefore(s, f);
    }
  } catch (e) {
    // 容错处理
    console.error('FingerPrint Error', e);
  }
})();

代码后续调整

  1. 需要判断:如果已有localStorage,则不再额外重新生成