在前端开发中,出于安全和隐私的考虑,浏览器不允许直接获取硬件的唯一标识(如 MAC 地址、CPU 序列号等)。但可以通过以下方法生成设备指纹(Device Fingerprint),近似实现设备唯一标识:


1. 组合浏览器特性生成指纹

通过收集浏览器和系统的多种信息,生成唯一性较高的字符串:

const fingerprint = {
  userAgent: navigator.userAgent,
  language: navigator.language,
  screen: {
    width: screen.width,
    height: screen.height,
    colorDepth: screen.colorDepth,
  },
  timezone: new Date().getTimezoneOffset(),
  plugins: Array.from(navigator.plugins).map(p => p.name).join(','),
  webglVendor: (() => {
    const canvas = document.createElement('canvas');
    const gl = canvas.getContext('webgl');
    return gl?.getParameter(gl.VENDOR);
  })(),
  fonts: (() => {
    const fonts = [];
    const testString = "abcdefghijklmnopqrstuvwxyz";
    const testFont = "Comic Sans MS";
    const ctx = document.createElement('canvas').getContext('2d');
    ctx.font = '72px monospace';
    const defaultWidth = ctx.measureText(testString).width;
    ctx.font = `72px ${testFont}, monospace`;
    if (ctx.measureText(testString).width !== defaultWidth) {
      fonts.push(testFont);
    }
    return fonts;
  })(),
};

// 生成哈希(例如使用 SHA-256)
const hash = async (data) => {
  const encoder = new TextEncoder();
  const hashBuffer = await crypto.subtle.digest('SHA-256', encoder.encode(JSON.stringify(data)));
  return Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('');
};

hash(fingerprint).then(console.log); // 输出设备指纹

2. 使用第三方库

一些开源库(如 FingerprintJS)封装了更复杂的指纹生成逻辑:

# 安装 FingerprintJS
npm install @fingerprintjs/fingerprintjs
import FingerprintJS from '@fingerprintjs/fingerprintjs';

(async () => {
  const fp = await FingerprintJS.load();
  const result = await fp.get();
  console.log(result.visitorId); // 生成的设备指纹
})();

3. Canvas 指纹

通过 Canvas 渲染的微小差异生成唯一标识:

function getCanvasFingerprint() {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  ctx.textBaseline = 'top';
  ctx.font = '14px Arial';
  ctx.fillStyle = '#f60';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = '#069';
  ctx.fillText('Hello, Fingerprint', 2, 15);
  return canvas.toDataURL();
}

4. WebRTC 泄露本地 IP

(注意:部分浏览器已限制此行为)

const getLocalIP = (callback) => {
  const pc = new RTCPeerConnection({ iceServers: [] });
  pc.createDataChannel('');
  pc.createOffer().then(offer => pc.setLocalDescription(offer));
  pc.onicecandidate = (ice) => {
    if (ice.candidate?.candidate?.match(/(\d+\.\d+\.\d+\.\d+)/)) {
      callback(RegExp.$1);
    }
  };
};

getLocalIP(ip => console.log('Local IP:', ip));

注意事项:

  1. 隐私合规:收集设备信息需遵循 GDPR、CCPA 等隐私法规,明确告知用户并获取同意。
  2. 不可靠性:设备指纹可能因浏览器设置、系统更新或用户行为(如隐私模式)而变化。
  3. 结合后端:可结合 IP、登录会话或 Cookie 增强识别稳定性。

替代方案

  • 持久化存储:使用 localStorageIndexedDB 存储生成的 UUID。
  • 用户登录系统:通过账号体系追踪用户而非设备。

如果需要真正的硬件级唯一标识,通常需通过原生应用(如 Electron、React Native)或与后端配合实现。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐