简介
FingerprintJS是一个开源的、客户端的浏览器指纹库,它查询浏览器属性,并从这些属性中计算出一个散列的访问者标识符。与cookie和本地存储不同,在隐身/私密模式下,甚至当浏览器数据被清除时,指纹仍然保持不变。
它允许你快速获取到一个浏览器的指纹。它通过收集各种浏览器和设备的信息来生成一个相对唯一的ID。它比简单的用户代理字符串检测更加可靠和精确。
它提供一种更加精确、可靠且对用户相对透明的方式,来识别和跟踪用户,特别是在网络安全、欺诈检测、在线广告和个性化内容展示等领域具有广泛的应用。
背景
如何在没有明确用户登录信息的情况下,识别和跟踪用户或设备。
传统的识别方法,如基于IP地址或者Cookies的跟踪,存在一些明显的局限性和缺点:
-
IP地址:用户的IP地址可能会变化(比如通过移动网络或VPN),并且很多用户可能共享同一个IP地址(如在同一个家庭或办公室网络中)。
-
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:
官网:
疑问点
- id变化的时机了解
浏览器无痕模式不会影响id计算
基本只有在浏览器修改、版本变更、时区等
可能会出现不同的用户,browserId相同的情况
- 版本与收费
| 版本 | 收费 | 准确度 | 文档 | |
|---|---|---|---|---|
| v4 | 用于生产收费fingerprint.com/blog/finger… | |||
| v3 | 开源 github.com/fingerprint… | 50% | github.com/fingerprint… |
- 无法覆盖面
-
baseconfig不接入:baseconfig的时机早于browserId
-
神策买点需要接入:埋点接口如要接入browserId,需额外配置
-
华为云APM不需要接入
-
其他未统一使用axios的请求不需要接入
- 浏览器兼容
- 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);
}
})();
代码后续调整
- 需要判断:如果已有localStorage,则不再额外重新生成