// 使用IIFE封装防止污染全局变量 (function (window) { // 配置参数 const defaultConfig = { webgl: true, audio: true, deviceInfo: true, }; // 创建全局对象 window.DeviceFingerprint = { init: function (config = {}) { // 等待DOM加载完成 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this._initialize(config)); } else { this._initialize(config); } return this; }, // 新增实际初始化方法 _initialize: function (config) { this.config = { ...defaultConfig, ...config }; this._loadDependencies() .then(() => { this._injectCanvasElements(); }) .catch((error) => { console.error('依赖加载失败:', error); }); }, // 自动注入需要的canvas元素 _injectCanvasElements: function () { if (!document.getElementById('fp-canvas')) { const canvas = document.createElement('canvas'); canvas.id = 'fp-canvas'; canvas.style.display = 'block'; document.body.appendChild(canvas); } }, _getIP: async function () { const endpoints = [ // 'https://api.ipify.org?format=json', // 主接口 'https://ipapi.co/json/', // 备用接口1 // 'https://ipinfo.io/json' // 备用接口2 ]; const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); try { // 尝试所有接口直到成功 for (const url of endpoints) { try { const response = await fetch(url, { signal: controller.signal, }); if (!response.ok) throw new Error('响应异常'); const data = await response.json(); return data.ip || data.ipAddress || '未知IP'; } catch (error) { console.warn(`接口 ${url} 请求失败:`, error.message); } } return '获取失败'; } catch (error) { console.error('IP获取最终失败:', error); return '获取失败'; } finally { clearTimeout(timeoutId); } }, // 统一获取所有指纹 async getAllFingerprints() { // 等待MD5库加载 if (!window.hex_md5) { await this._loadDependencies(); } const results = {}; // 添加null检查 if (!document.getElementById('fp-canvas')) { throw new Error('Canvas元素未成功创建'); } if (this.config.webgl) { results.webgl = this._getWebGLFingerprint(); } if (this.config.deviceInfo) { results.device = this._getDeviceFingerprint(); } return results; }, getWebGLFingerprint: async function () { // 等待依赖加载完成 if (!window.hex_md5) { await this._loadDependencies(); } try { // 检查canvas元素是否存在 if (!document.getElementById('fp-canvas')) { throw new Error('Canvas元素未找到,请先调用初始化方法'); } // 调用内部方法获取指纹 return this._getWebGLFingerprint(); } catch (error) { console.error('获取WebGL指纹失败:', error); return null; } }, _getWebGLFingerprint: async function () { const canvas = document.createElement('canvas'); const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); if (!gl) return 'unsupported'; // 获取WebGL基础参数 const params = [ gl.getParameter(gl.VERSION), gl.getParameter(gl.SHADING_LANGUAGE_VERSION), gl.getParameter(gl.VENDOR), gl.getParameter(gl.RENDERER), gl.getParameter(gl.MAX_TEXTURE_SIZE), gl.getParameter(gl.MAX_RENDERBUFFER_SIZE), ]; // 获取屏幕尺寸 const screen = `${window.screen.width}x${window.screen.height}x${window.screen.colorDepth}`; console.log('screen', screen); console.log('params', params); // 组合关键特征 const fingerprintData = `${params.join('|')}|${screen}`; return hex_md5(fingerprintData); }, _getDeviceFingerprint: function () { try { const deviceInfo = { screen: `${screen.width}x${screen.height}`, colorDepth: screen.colorDepth, timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, platform: navigator.platform, userAgent: navigator.userAgent, languages: navigator.languages.join(','), hardwareConcurrency: navigator.hardwareConcurrency || 'unknown', }; return hex_md5(JSON.stringify(deviceInfo)); } catch (error) { console.error('Device info error:', error); return null; } }, // 修改MD5加载方法 _loadDependencies: function () { return new Promise((resolve, reject) => { if (window.hex_md5) return resolve(); const script = document.createElement('script'); script.src = './md5.js'; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }); }, getWebGLFingerprint: async function () { // 等待依赖加载完成 if (!window.hex_md5) { await this._loadDependencies(); } try { // 检查canvas元素是否存在 if (!document.getElementById('fp-canvas')) { throw new Error('Canvas元素未找到,请先调用初始化方法'); } // 调用内部方法获取指纹 return this._getWebGLFingerprint(); } catch (error) { console.error('获取WebGL指纹失败:', error); return null; } }, }; // 自动初始化(可选) window.DeviceFingerprint.init(); })(window);