• 浏览器指纹
    • 浏览器指纹可用于识别浏览器,保存简单的记录而用户可以免登录使用,提升用户体验。
    • 支持PC端和移动端浏览器;
  • 硬件指纹
    • 同一设备,不同浏览器 → 相同指纹
    • 删除缓存后重新生成 → 相同指纹
    • 不同设备 → 不同指纹
    • 基于真实硬件特征,不是浏览器配置

# 一、同一设备(PC/平板/移动设备如手机)不同浏览器可生成相同指纹,删除后恢复率及识别率达到80%

devicefingeruuid.1.0.1.js

/**
 * 设备指纹识别 - 生成稳定的deviceId
 * 支持PC端和移动端浏览器
 * @version 1.0.1
 */

class DeviceFingerprint {
    constructor() {
        this.storageKey = 'device_fingerprint_uuid';
        this.localStorageKey = 'device_fp_data';
        this.fingerprintData = null;
    }

    /**
     * 初始化设备指纹
     * @returns {Promise<string>} deviceId
     */
    async init() {
        try {
            let deviceId = this.getStoredDeviceId();
            
            if (deviceId) {
                console.log('从存储中获取到deviceId:', deviceId);
                this.updateLastAccessed();
                return deviceId;
            }

            const fingerprint = await this.generateFingerprint();
            deviceId = this.generateUUID(fingerprint);
            
            const recoveredDeviceId = await this.tryRecoverDeviceId(fingerprint);
            if (recoveredDeviceId) {
                console.log('通过指纹数据恢复deviceId:', recoveredDeviceId);
                deviceId = recoveredDeviceId;
            }
            
            this.storeFingerprintData(fingerprint, deviceId);
            
            console.log('生成新的deviceId:', deviceId);
            return deviceId;
            
        } catch (error) {
            console.error('设备指纹生成失败:', error);
            return this.generateFallbackUUID();
        }
    }

    /**
     * 尝试通过指纹数据恢复deviceId
     * @param {Object} newFingerprint 
     * @returns {string|null}
     */
    async tryRecoverDeviceId(newFingerprint) {
        try {
            if (typeof localStorage !== 'undefined') {
                const storedData = localStorage.getItem(this.localStorageKey);
                if (storedData) {
                    const historyData = JSON.parse(storedData);
                    const historyFingerprint = historyData.fingerprint;
                    
                    if (this.compareFingerprints(historyFingerprint, newFingerprint)) {
                        console.log('指纹匹配,恢复历史deviceId');
                        return historyData.deviceId;
                    }
                }
            }
            
            return null;
        } catch (error) {
            console.warn('恢复deviceId失败:', error);
            return null;
        }
    }

    /**
     * 比较两个指纹的稳定性特征
     * @param {Object} fp1 
     * @param {Object} fp2 
     * @returns {boolean}
     */
    compareFingerprints(fp1, fp2) {
        const stableAttributes = [
            'userAgent',
            'language',
            'languages',
            'screenWidth', 
            'screenHeight',
            'colorDepth',
            'pixelDepth',
            'vendor',
            'platform',
            'hardwareConcurrency',
            'deviceMemory',
            'timezone',
            'timezoneOffset',
            'canvasFingerprint',
            'webglFingerprint',
            'fonts',
            'plugins',
            'touchSupport'
        ];
        
        let matchCount = 0;
        let totalCompared = 0;
        
        for (const attr of stableAttributes) {
            if (fp1[attr] && fp2[attr]) {
                totalCompared++;
                if (this.normalizeValue(fp1[attr]) === this.normalizeValue(fp2[attr])) {
                    matchCount++;
                }
            }
        }
        
        const matchRate = matchCount / totalCompared;
        console.log(`指纹匹配率: ${matchRate.toFixed(2)} (${matchCount}/${totalCompared})`);
        
        return matchRate >= 0.8;
    }

    /**
     * 标准化值用于比较
     * @param {*} value 
     * @returns {string}
     */
    normalizeValue(value) {
        if (typeof value === 'object') {
            return JSON.stringify(value);
        }
        return String(value).toLowerCase().trim();
    }

    /**
     * 从本地存储获取deviceId
     * @returns {string|null}
     */
    getStoredDeviceId() {
        try {
            if (typeof localStorage !== 'undefined') {
                const stored = localStorage.getItem(this.storageKey);
                if (stored) {
                    return stored;
                }
            }
            
            if (typeof sessionStorage !== 'undefined') {
                const stored = sessionStorage.getItem(this.storageKey);
                if (stored) {
                    return stored;
                }
            }
            
            return null;
        } catch (error) {
            console.warn('读取存储失败:', error);
            return null;
        }
    }

    /**
     * 生成设备指纹
     * @returns {Promise<Object>}
     */
    async generateFingerprint() {
        const fingerprint = {
            userAgent: navigator.userAgent,
            language: navigator.language,
            languages: navigator.languages ? navigator.languages.join(',') : '',
            screenWidth: screen.width,
            screenHeight: screen.height,
            colorDepth: screen.colorDepth,
            pixelDepth: screen.pixelDepth,
            vendor: navigator.vendor || '',
            platform: navigator.platform,
            hardwareConcurrency: navigator.hardwareConcurrency || 0,
            deviceMemory: navigator.deviceMemory || 0,
            timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
            timezoneOffset: new Date().getTimezoneOffset(),
            canvasFingerprint: await this.getCanvasFingerprint(),
            webglFingerprint: this.getWebGLFingerprint(),
            audioFingerprint: await this.getAudioFingerprint(),
            fonts: this.getFonts(),
            plugins: this.getPlugins(),
            touchSupport: this.getTouchSupport(),
            cookieEnabled: navigator.cookieEnabled,
            doNotTrack: navigator.doNotTrack || 'unknown',
            product: navigator.product || '',
            productSub: navigator.productSub || ''
        };

        return fingerprint;
    }

    /**
     * 生成Canvas指纹
     * @returns {Promise<string>}
     */
    async getCanvasFingerprint() {
        try {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            
            canvas.width = 200;
            canvas.height = 50;
            
            ctx.textBaseline = 'top';
            ctx.font = '14px Arial';
            ctx.fillStyle = '#f60';
            ctx.fillRect(125, 1, 62, 20);
            ctx.fillStyle = '#069';
            ctx.fillText('Device Fingerprint', 2, 15);
            ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
            ctx.fillText('Device Fingerprint', 4, 17);
            
            ctx.strokeStyle = 'rgb(200, 0, 0)';
            ctx.beginPath();
            ctx.moveTo(10, 30);
            ctx.lineTo(150, 30);
            ctx.stroke();
            
            return canvas.toDataURL();
        } catch (error) {
            return 'canvas_unsupported';
        }
    }

    /**
     * 生成WebGL指纹
     * @returns {string}
     */
    getWebGLFingerprint() {
        try {
            const canvas = document.createElement('canvas');
            const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
            
            if (!gl) {
                return 'webgl_unsupported';
            }
            
            const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
            if (debugInfo) {
                const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
                const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
                return `${vendor}|${renderer}`;
            }
            
            const version = gl.getParameter(gl.VERSION);
            const shadingLanguageVersion = gl.getParameter(gl.SHADING_LANGUAGE_VERSION);
            return `${version}|${shadingLanguageVersion}`;
        } catch (error) {
            return 'webgl_error';
        }
    }

    /**
     * 生成音频指纹
     * @returns {Promise<string>}
     */
    async getAudioFingerprint() {
        try {
            const audioContext = new (window.AudioContext || window.webkitAudioContext)();
            const oscillator = audioContext.createOscillator();
            const analyser = audioContext.createAnalyser();
            
            oscillator.type = 'sine';
            oscillator.frequency.value = 440;
            
            oscillator.connect(analyser);
            analyser.connect(audioContext.destination);
            
            oscillator.start();
            
            await new Promise(resolve => setTimeout(resolve, 50));
            
            const data = new Uint8Array(analyser.frequencyBinCount);
            analyser.getByteFrequencyData(data);
            
            oscillator.stop();
            audioContext.close();
            
            const stableData = Array.from(data.slice(0, 20));
            return stableData.join(',');
        } catch (error) {
            return 'audio_unsupported';
        }
    }

    /**
     * 获取字体列表
     * @returns {string}
     */
    getFonts() {
        const fontList = [
            'Arial', 'Arial Black', 'Arial Narrow', 'Times New Roman',
            'Courier New', 'Verdana', 'Georgia', 'Palatino',
            'Garamond', 'Bookman', 'Comic Sans MS', 'Trebuchet MS',
            'Impact', 'Tahoma', 'Helvetica', 'Microsoft YaHei',
            'SimSun', 'SimHei', 'KaiTi', 'FangSong'
        ];
        
        const availableFonts = [];
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        
        const baseText = 'abcdefghijklmnopqrstuvwxyz0123456789';
        const baseWidth = ctx.measureText(baseText).width;
        
        fontList.forEach(font => {
            ctx.font = `72px ${font}, monospace`;
            const width = ctx.measureText(baseText).width;
            if (width !== baseWidth) {
                availableFonts.push(font);
            }
        });
        
        return availableFonts.join(',');
    }

    /**
     * 获取插件信息
     * @returns {string}
     */
    getPlugins() {
        if (!navigator.plugins) {
            return 'no_plugins';
        }
        
        const plugins = [];
        for (let i = 0; i < navigator.plugins.length; i++) {
            plugins.push(navigator.plugins[i].name);
        }
        
        return plugins.join(',');
    }

    /**
     * 获取触摸支持信息
     * @returns {string}
     */
    getTouchSupport() {
        const touchSupport = {
            maxTouchPoints: navigator.maxTouchPoints || 0,
            touchEvent: 'ontouchstart' in window,
            pointerEvent: 'onpointerdown' in window
        };
        
        return JSON.stringify(touchSupport);
    }

    /**
     * 基于指纹数据生成UUID
     * @param {Object} fingerprint 
     * @returns {string}
     */
    generateUUID(fingerprint) {
        const stableFingerprintStr = [
            fingerprint.userAgent,
            fingerprint.platform,
            fingerprint.screenWidth,
            fingerprint.screenHeight,
            fingerprint.hardwareConcurrency,
            fingerprint.webglFingerprint,
            fingerprint.timezone
        ].join('|');
        
        let hash = 0;
        for (let i = 0; i < stableFingerprintStr.length; i++) {
            const char = stableFingerprintStr.charCodeAt(i);
            hash = ((hash << 7) - hash) + char;
            hash = hash & 0x7FFFFFFF;
        }
        
        const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
        let result = '';
        
        for (let i = 0; i < template.length; i++) {
            const c = template[i];
            if (c === 'x' || c === 'y') {
                const r = (hash + i * 13) % 16;
                hash = Math.floor(hash / 16);
                result += (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
            } else {
                result += c;
            }
        }
        
        return result;
    }

    /**
     * 降级方案:生成随机UUID
     * @returns {string}
     */
    generateFallbackUUID() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            const r = Math.random() * 16 | 0;
            return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        });
    }

    /**
     * 存储设备指纹数据
     * @param {Object} fingerprint 
     * @param {string} deviceId 
     */
    storeFingerprintData(fingerprint, deviceId) {
        try {
            if (typeof localStorage !== 'undefined') {
                localStorage.setItem(this.storageKey, deviceId);
            }
            if (typeof sessionStorage !== 'undefined') {
                sessionStorage.setItem(this.storageKey, deviceId);
            }
            
            const storageData = {
                deviceId: deviceId,
                fingerprint: fingerprint,
                createdAt: new Date().toISOString(),
                lastAccessed: new Date().toISOString()
            };
            
            if (typeof localStorage !== 'undefined') {
                localStorage.setItem(this.localStorageKey, JSON.stringify(storageData));
            }
            
        } catch (error) {
            console.warn('存储设备指纹数据失败:', error);
        }
    }

    /**
     * 更新最后访问时间
     */
    updateLastAccessed() {
        try {
            if (typeof localStorage !== 'undefined') {
                const storedData = localStorage.getItem(this.localStorageKey);
                if (storedData) {
                    const data = JSON.parse(storedData);
                    data.lastAccessed = new Date().toISOString();
                    localStorage.setItem(this.localStorageKey, JSON.stringify(data));
                }
            }
        } catch (error) {
            console.warn('更新最后访问时间失败:', error);
        }
    }

    /**
     * 获取设备信息摘要
     * @returns {Object}
     */
    getDeviceInfo() {
        return {
            deviceId: this.getStoredDeviceId(),
            userAgent: navigator.userAgent,
            platform: navigator.platform,
            screen: `${screen.width}x${screen.height}`,
            language: navigator.language,
            timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
        };
    }

    /**
     * 清除设备指纹数据
     */
    clear() {
        try {
            if (typeof localStorage !== 'undefined') {
                localStorage.removeItem(this.storageKey);
                localStorage.removeItem(this.localStorageKey);
            }
            if (typeof sessionStorage !== 'undefined') {
                sessionStorage.removeItem(this.storageKey);
            }
            console.log('设备指纹数据已清除');
        } catch (error) {
            console.error('清除设备指纹数据失败:', error);
        }
    }
}

const deviceFingerprint = new DeviceFingerprint();

if (typeof module !== 'undefined' && module.exports) {
    module.exports = deviceFingerprint;
} else {
    window.deviceFingerprint = deviceFingerprint;
}

document.addEventListener('DOMContentLoaded', async function() {
    try {
        const deviceId = await deviceFingerprint.init();
        
        window.deviceId = deviceId;
        
        const event = new CustomEvent('deviceIdReady', {
            detail: { deviceId: deviceId }
        });
        document.dispatchEvent(event);
        
        console.log('设备指纹初始化完成:', deviceId);
        
    } catch (error) {
        console.error('设备指纹初始化失败:', error);
    }
});

if (!window.Promise) {
    console.warn('当前浏览器不支持Promise,设备指纹功能可能无法正常工作');
}

window.getDeviceId = function() {
    return window.deviceId || deviceFingerprint.getStoredDeviceId();
};

# 二、不同设备相同浏览器生成不同指纹【进阶版】

# 1. 实现代码

devicefingeruuid.1.0.2.js

/**
 * 设备指纹识别 - 生成稳定的deviceId
 * 支持PC端和移动端浏览器
 * @version 1.0.2
 */

class DeviceFingerprint {
    constructor() {
        this.storageKey = 'device_fingerprint_uuid';
        this.localStorageKey = 'device_fp_data';
        this.fingerprintData = null;
    }

    /**
     * 初始化设备指纹
     * @returns {Promise<string>} deviceId
     */
    async init() {
        try {
            let deviceId = this.getStoredDeviceId();
            
            if (deviceId) {
                console.log('从存储中获取到deviceId:', deviceId);
                this.updateLastAccessed();
                return deviceId;
            }

            const fingerprint = await this.generateFingerprint();
            deviceId = this.generateUUID(fingerprint);
            
            const recoveredDeviceId = await this.tryRecoverDeviceId(fingerprint);
            if (recoveredDeviceId) {
                console.log('通过指纹数据恢复deviceId:', recoveredDeviceId);
                deviceId = recoveredDeviceId;
            }
            
            this.storeFingerprintData(fingerprint, deviceId);
            
            console.log('生成新的deviceId:', deviceId);
            return deviceId;
            
        } catch (error) {
            console.error('设备指纹生成失败:', error);
            return this.generateFallbackUUID();
        }
    }

    /**
     * 尝试通过指纹数据恢复deviceId
     * @param {Object} newFingerprint 
     * @returns {string|null}
     */
    async tryRecoverDeviceId(newFingerprint) {
        try {
            if (typeof localStorage !== 'undefined') {
                const storedData = localStorage.getItem(this.localStorageKey);
                if (storedData) {
                    const historyData = JSON.parse(storedData);
                    const historyFingerprint = historyData.fingerprint;
                    
                    if (this.compareFingerprints(historyFingerprint, newFingerprint)) {
                        console.log('指纹匹配,恢复历史deviceId');
                        return historyData.deviceId;
                    }
                }
            }
            
            return null;
        } catch (error) {
            console.warn('恢复deviceId失败:', error);
            return null;
        }
    }

    /**
     * 比较两个指纹的稳定性特征
     * @param {Object} fp1 
     * @param {Object} fp2 
     * @returns {boolean}
     */
    compareFingerprints(fp1, fp2) {
        const stableAttributes = [
            'userAgent',
            'language',
            'languages',
            'screenWidth', 
            'screenHeight',
            'colorDepth',
            'pixelDepth',
            'vendor',
            'platform',
            'hardwareConcurrency',
            'deviceMemory',
            'timezone',
            'timezoneOffset',
            'canvasFingerprint',
            'webglFingerprint',
            'webglVendor',
            'webglRenderer',
            'audioFingerprint',
            'fonts',
            'plugins',
            'touchSupport',
            'performanceTiming',
            'mathPrecision'
        ];
        
        let matchCount = 0;
        let totalCompared = 0;
        
        for (const attr of stableAttributes) {
            if (fp1[attr] && fp2[attr]) {
                totalCompared++;
                if (this.normalizeValue(fp1[attr]) === this.normalizeValue(fp2[attr])) {
                    matchCount++;
                }
            }
        }
        
        const matchRate = matchCount / totalCompared;
        console.log(`指纹匹配率: ${matchRate.toFixed(2)} (${matchCount}/${totalCompared})`);
        
        return matchRate >= 0.8;
    }

    /**
     * 标准化值用于比较
     * @param {*} value 
     * @returns {string}
     */
    normalizeValue(value) {
        if (typeof value === 'object') {
            return JSON.stringify(value);
        }
        return String(value).toLowerCase().trim();
    }

    /**
     * 从本地存储获取deviceId
     * @returns {string|null}
     */
    getStoredDeviceId() {
        try {
            if (typeof localStorage !== 'undefined') {
                const stored = localStorage.getItem(this.storageKey);
                if (stored) {
                    return stored;
                }
            }
            
            if (typeof sessionStorage !== 'undefined') {
                const stored = sessionStorage.getItem(this.storageKey);
                if (stored) {
                    return stored;
                }
            }
            
            return null;
        } catch (error) {
            console.warn('读取存储失败:', error);
            return null;
        }
    }

    /**
     * 生成设备指纹 - 增强硬件特征
     * @returns {Promise<Object>}
     */
    async generateFingerprint() {
        const fingerprint = {
            // 基础浏览器信息
            userAgent: navigator.userAgent,
            language: navigator.language,
            languages: navigator.languages ? navigator.languages.join(',') : '',
            vendor: navigator.vendor || '',
            platform: navigator.platform,
            
            // 屏幕和显示信息
            screenWidth: screen.width,
            screenHeight: screen.height,
            colorDepth: screen.colorDepth,
            pixelDepth: screen.pixelDepth,
            availWidth: screen.availWidth,
            availHeight: screen.availHeight,
            devicePixelRatio: window.devicePixelRatio || 1,
            
            // 硬件信息
            hardwareConcurrency: navigator.hardwareConcurrency || 0,
            deviceMemory: navigator.deviceMemory || 0,
            maxTouchPoints: navigator.maxTouchPoints || 0,
            
            // 时区和语言
            timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
            timezoneOffset: new Date().getTimezoneOffset(),
            
            // 图形指纹 - 增强硬件区分度
            canvasFingerprint: await this.getCanvasFingerprint(),
            webglFingerprint: this.getWebGLFingerprint(),
            webglVendor: this.getWebGLVendor(),
            webglRenderer: this.getWebGLRenderer(),
            webglExtensions: this.getWebGLExtensions(),
            
            // 音频指纹 - 增强硬件区分度
            audioFingerprint: await this.getAudioFingerprint(),
            audioContextFingerprint: await this.getAudioContextFingerprint(),
            
            // 字体列表
            fonts: this.getFonts(),
            
            // 插件信息
            plugins: this.getPlugins(),
            mimeTypes: this.getMimeTypes(),
            
            // 触摸支持
            touchSupport: this.getTouchSupport(),
            
            // 性能特征 - 硬件相关
            performanceTiming: this.getPerformanceTiming(),
            mathPrecision: this.getMathPrecision(),
            
            // 其他特征
            cookieEnabled: navigator.cookieEnabled,
            doNotTrack: navigator.doNotTrack || 'unknown',
            product: navigator.product || '',
            productSub: navigator.productSub || '',
            
            // 增强硬件特征
            deviceOrientation: this.getDeviceOrientation(),
            connectionInfo: this.getConnectionInfo(),
            batteryInfo: await this.getBatteryInfo(),
            mediaDevices: await this.getMediaDevicesInfo()
        };

        return fingerprint;
    }

    /**
     * 生成Canvas指纹 - 增强硬件特征
     * @returns {Promise<string>}
     */
    async getCanvasFingerprint() {
        try {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            
            canvas.width = 240;
            canvas.height = 60;
            
            // 基础绘制
            ctx.textBaseline = 'top';
            ctx.font = '14px "Arial"';
            ctx.fillStyle = '#f60';
            ctx.fillRect(125, 1, 62, 20);
            ctx.fillStyle = '#069';
            ctx.fillText('Device Fingerprint HW', 2, 15);
            ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
            ctx.fillText('Device Fingerprint HW', 4, 17);
            
            // 添加复杂图形 - 不同GPU渲染会有差异
            ctx.strokeStyle = 'rgb(200, 0, 0)';
            ctx.beginPath();
            ctx.moveTo(10, 30);
            ctx.lineTo(150, 30);
            ctx.stroke();
            
            // 渐变和阴影 - 硬件加速相关
            const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
            gradient.addColorStop(0, 'red');
            gradient.addColorStop(0.5, 'blue');
            gradient.addColorStop(1, 'green');
            ctx.fillStyle = gradient;
            ctx.fillRect(160, 10, 70, 40);
            
            // 添加文本阴影
            ctx.shadowBlur = 2;
            ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
            ctx.shadowOffsetX = 1;
            ctx.shadowOffsetY = 1;
            ctx.fillStyle = 'purple';
            ctx.fillText('GPU Test', 10, 45);
            
            return canvas.toDataURL();
        } catch (error) {
            return 'canvas_unsupported';
        }
    }

    /**
     * 生成WebGL指纹
     * @returns {string}
     */
    getWebGLFingerprint() {
        try {
            const canvas = document.createElement('canvas');
            const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
            
            if (!gl) {
                return 'webgl_unsupported';
            }
            
            const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
            if (debugInfo) {
                const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
                const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
                return `${vendor}|${renderer}`;
            }
            
            const version = gl.getParameter(gl.VERSION);
            const shadingLanguageVersion = gl.getParameter(gl.SHADING_LANGUAGE_VERSION);
            return `${version}|${shadingLanguageVersion}`;
        } catch (error) {
            return 'webgl_error';
        }
    }

    /**
     * 获取WebGL供应商信息
     * @returns {string}
     */
    getWebGLVendor() {
        try {
            const canvas = document.createElement('canvas');
            const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
            
            if (!gl) return 'webgl_unsupported';
            
            const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
            return debugInfo ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) : gl.getParameter(gl.VENDOR);
        } catch (error) {
            return 'webgl_error';
        }
    }

    /**
     * 获取WebGL渲染器信息
     * @returns {string}
     */
    getWebGLRenderer() {
        try {
            const canvas = document.createElement('canvas');
            const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
            
            if (!gl) return 'webgl_unsupported';
            
            const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
            return debugInfo ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : gl.getParameter(gl.RENDERER);
        } catch (error) {
            return 'webgl_error';
        }
    }

    /**
     * 获取WebGL扩展列表
     * @returns {string}
     */
    getWebGLExtensions() {
        try {
            const canvas = document.createElement('canvas');
            const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
            
            if (!gl) return 'webgl_unsupported';
            
            const extensions = gl.getSupportedExtensions();
            return extensions ? extensions.sort().join(',') : 'no_extensions';
        } catch (error) {
            return 'webgl_error';
        }
    }

    /**
     * 生成音频指纹 - 增强硬件特征
     * @returns {Promise<string>}
     */
    async getAudioFingerprint() {
        try {
            const audioContext = new (window.AudioContext || window.webkitAudioContext)();
            const oscillator = audioContext.createOscillator();
            const analyser = audioContext.createAnalyser();
            const compressor = audioContext.createDynamicsCompressor();
            
            oscillator.type = 'sine';
            oscillator.frequency.value = 440;
            
            oscillator.connect(compressor);
            compressor.connect(analyser);
            analyser.connect(audioContext.destination);
            
            analyser.fftSize = 2048;
            const bufferLength = analyser.frequencyBinCount;
            
            oscillator.start();
            
            await new Promise(resolve => setTimeout(resolve, 100));
            
            const frequencyData = new Uint8Array(bufferLength);
            const timeDomainData = new Uint8Array(bufferLength);
            
            analyser.getByteFrequencyData(frequencyData);
            analyser.getByteTimeDomainData(timeDomainData);
            
            oscillator.stop();
            audioContext.close();
            
            // 结合频域和时域数据,增加区分度
            const combinedData = [
                ...Array.from(frequencyData.slice(0, 50)),
                ...Array.from(timeDomainData.slice(0, 50))
            ];
            
            return combinedData.join(',');
        } catch (error) {
            return 'audio_unsupported';
        }
    }

    /**
     * 获取音频上下文指纹
     * @returns {Promise<string>}
     */
    async getAudioContextFingerprint() {
        try {
            const audioContext = new (window.AudioContext || window.webkitAudioContext)();
            
            const info = {
                sampleRate: audioContext.sampleRate,
                baseLatency: audioContext.baseLatency || 'unknown',
                outputLatency: audioContext.outputLatency || 'unknown'
            };
            
            audioContext.close();
            return JSON.stringify(info);
        } catch (error) {
            return 'audio_context_unsupported';
        }
    }

    /**
     * 获取字体列表
     * @returns {string}
     */
    getFonts() {
        const fontList = [
            'Arial', 'Arial Black', 'Arial Narrow', 'Times New Roman',
            'Courier New', 'Verdana', 'Georgia', 'Palatino',
            'Garamond', 'Bookman', 'Comic Sans MS', 'Trebuchet MS',
            'Impact', 'Tahoma', 'Helvetica', 'Microsoft YaHei',
            'SimSun', 'SimHei', 'KaiTi', 'FangSong',
            'Webdings', 'Wingdings', 'Symbol', 'Zapf Dingbats'
        ];
        
        const availableFonts = [];
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        
        const baseText = 'abcdefghijklmnopqrstuvwxyz0123456789';
        const baseWidth = ctx.measureText(baseText).width;
        
        fontList.forEach(font => {
            ctx.font = `72px ${font}, monospace`;
            const width = ctx.measureText(baseText).width;
            if (width !== baseWidth) {
                availableFonts.push(font);
            }
        });
        
        return availableFonts.join(',');
    }

    /**
     * 获取插件信息
     * @returns {string}
     */
    getPlugins() {
        if (!navigator.plugins) {
            return 'no_plugins';
        }
        
        const plugins = [];
        for (let i = 0; i < navigator.plugins.length; i++) {
            plugins.push(navigator.plugins[i].name);
        }
        
        return plugins.sort().join(',');
    }

    /**
     * 获取MIME类型信息
     * @returns {string}
     */
    getMimeTypes() {
        if (!navigator.mimeTypes) {
            return 'no_mimeTypes';
        }
        
        const mimeTypes = [];
        for (let i = 0; i < navigator.mimeTypes.length; i++) {
            mimeTypes.push(navigator.mimeTypes[i].type);
        }
        
        return mimeTypes.sort().join(',');
    }

    /**
     * 获取触摸支持信息
     * @returns {string}
     */
    getTouchSupport() {
        const touchSupport = {
            maxTouchPoints: navigator.maxTouchPoints || 0,
            touchEvent: 'ontouchstart' in window,
            pointerEvent: 'onpointerdown' in window,
            msMaxTouchPoints: navigator.msMaxTouchPoints || 0
        };
        
        return JSON.stringify(touchSupport);
    }

    /**
     * 获取性能特征
     * @returns {string}
     */
    getPerformanceTiming() {
        if (!window.performance || !performance.timing) {
            return 'performance_unsupported';
        }
        
        const timing = performance.timing;
        const perfData = {
            navigationStart: timing.navigationStart,
            domainLookupEnd: timing.domainLookupEnd - timing.domainLookupStart,
            connectEnd: timing.connectEnd - timing.connectStart,
            responseEnd: timing.responseEnd - timing.requestStart,
            domLoading: timing.domLoading - timing.navigationStart
        };
        
        return JSON.stringify(perfData);
    }

    /**
     * 获取数学计算精度
     * @returns {string}
     */
    getMathPrecision() {
        const tests = [
            Math.sin(1.234),
            Math.cos(2.345),
            Math.tan(3.456),
            Math.log(4.567),
            Math.exp(5.678)
        ];
        
        return tests.map(num => num.toFixed(15)).join(',');
    }

    /**
     * 获取设备方向
     * @returns {string}
     */
    getDeviceOrientation() {
        if (!window.screen) return 'unknown';
        
        const orientation = {
            orientation: screen.orientation ? screen.orientation.type : 'unknown',
            angle: screen.orientation ? screen.orientation.angle : 0
        };
        
        return JSON.stringify(orientation);
    }

    /**
     * 获取网络连接信息
     * @returns {string}
     */
    getConnectionInfo() {
        if (!navigator.connection) return 'connection_unsupported';
        
        const conn = navigator.connection;
        const info = {
            effectiveType: conn.effectiveType || 'unknown',
            downlink: conn.downlink || 0,
            rtt: conn.rtt || 0,
            saveData: conn.saveData || false
        };
        
        return JSON.stringify(info);
    }

    /**
     * 获取电池信息
     * @returns {Promise<string>}
     */
    async getBatteryInfo() {
        try {
            if (!navigator.getBattery) return 'battery_unsupported';
            
            const battery = await navigator.getBattery();
            const info = {
                charging: battery.charging,
                level: battery.level,
                chargingTime: battery.chargingTime,
                dischargingTime: battery.dischargingTime
            };
            
            return JSON.stringify(info);
        } catch (error) {
            return 'battery_error';
        }
    }

    /**
     * 获取媒体设备信息
     * @returns {Promise<string>}
     */
    async getMediaDevicesInfo() {
        try {
            if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
                return 'media_devices_unsupported';
            }
            
            const devices = await navigator.mediaDevices.enumerateDevices();
            const deviceInfo = devices.map(device => ({
                kind: device.kind,
                label: device.label,
                groupId: device.groupId
            }));
            
            return JSON.stringify(deviceInfo);
        } catch (error) {
            return 'media_devices_error';
        }
    }

    /**
     * 基于指纹数据生成UUID - 增强区分度
     * @param {Object} fingerprint 
     * @returns {string}
     */
    generateUUID(fingerprint) {
        // 使用更多硬件相关特征来增强区分度
        const hardwareFingerprintStr = [
            fingerprint.userAgent,
            fingerprint.platform,
            fingerprint.screenWidth,
            fingerprint.screenHeight,
            fingerprint.devicePixelRatio,
            fingerprint.hardwareConcurrency,
            fingerprint.deviceMemory,
            fingerprint.webglVendor,
            fingerprint.webglRenderer,
            fingerprint.audioContextFingerprint,
            fingerprint.mathPrecision,
            fingerprint.performanceTiming
        ].join('|');
        
        // 使用更复杂的哈希算法
        let hash = 0;
        for (let i = 0; i < hardwareFingerprintStr.length; i++) {
            const char = hardwareFingerprintStr.charCodeAt(i);
            hash = ((hash << 9) - hash) + char;
            hash = hash & 0x7FFFFFFF;
        }
        
        // 添加额外的随机熵来避免碰撞
        const extraEntropy = Math.random().toString(36).substring(2, 15);
        let entropyHash = 0;
        for (let i = 0; i < extraEntropy.length; i++) {
            entropyHash = ((entropyHash << 5) - entropyHash) + extraEntropy.charCodeAt(i);
            entropyHash = entropyHash & 0x7FFFFFFF;
        }
        
        const finalHash = (hash ^ entropyHash) & 0x7FFFFFFF;
        
        const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
        let result = '';
        
        for (let i = 0; i < template.length; i++) {
            const c = template[i];
            if (c === 'x' || c === 'y') {
                const r = (finalHash + i * 17) % 16;
                result += (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
            } else {
                result += c;
            }
        }
        
        return result;
    }

    /**
     * 降级方案:生成随机UUID
     * @returns {string}
     */
    generateFallbackUUID() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            const r = Math.random() * 16 | 0;
            return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        });
    }

    /**
     * 存储设备指纹数据
     * @param {Object} fingerprint 
     * @param {string} deviceId 
     */
    storeFingerprintData(fingerprint, deviceId) {
        try {
            if (typeof localStorage !== 'undefined') {
                localStorage.setItem(this.storageKey, deviceId);
            }
            if (typeof sessionStorage !== 'undefined') {
                sessionStorage.setItem(this.storageKey, deviceId);
            }
            
            const storageData = {
                deviceId: deviceId,
                fingerprint: fingerprint,
                createdAt: new Date().toISOString(),
                lastAccessed: new Date().toISOString()
            };
            
            if (typeof localStorage !== 'undefined') {
                localStorage.setItem(this.localStorageKey, JSON.stringify(storageData));
            }
            
        } catch (error) {
            console.warn('存储设备指纹数据失败:', error);
        }
    }

    /**
     * 更新最后访问时间
     */
    updateLastAccessed() {
        try {
            if (typeof localStorage !== 'undefined') {
                const storedData = localStorage.getItem(this.localStorageKey);
                if (storedData) {
                    const data = JSON.parse(storedData);
                    data.lastAccessed = new Date().toISOString();
                    localStorage.setItem(this.localStorageKey, JSON.stringify(data));
                }
            }
        } catch (error) {
            console.warn('更新最后访问时间失败:', error);
        }
    }

    /**
     * 获取设备信息摘要
     * @returns {Object}
     */
    getDeviceInfo() {
        return {
            deviceId: this.getStoredDeviceId(),
            userAgent: navigator.userAgent,
            platform: navigator.platform,
            screen: `${screen.width}x${screen.height}`,
            language: navigator.language,
            timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
        };
    }

    /**
     * 清除设备指纹数据
     */
    clear() {
        try {
            if (typeof localStorage !== 'undefined') {
                localStorage.removeItem(this.storageKey);
                localStorage.removeItem(this.localStorageKey);
            }
            if (typeof sessionStorage !== 'undefined') {
                sessionStorage.removeItem(this.storageKey);
            }
            console.log('设备指纹数据已清除');
        } catch (error) {
            console.error('清除设备指纹数据失败:', error);
        }
    }
}

const deviceFingerprint = new DeviceFingerprint();

if (typeof module !== 'undefined' && module.exports) {
    module.exports = deviceFingerprint;
} else {
    window.deviceFingerprint = deviceFingerprint;
}

document.addEventListener('DOMContentLoaded', async function() {
    try {
        const deviceId = await deviceFingerprint.init();
        
        window.deviceId = deviceId;
        
        const event = new CustomEvent('deviceIdReady', {
            detail: { deviceId: deviceId }
        });
        document.dispatchEvent(event);
        
        console.log('设备指纹初始化完成:', deviceId);
        
    } catch (error) {
        console.error('设备指纹初始化失败:', error);
    }
});

if (!window.Promise) {
    console.warn('当前浏览器不支持Promise,设备指纹功能可能无法正常工作');
}

window.getDeviceId = function() {
    return window.deviceId || deviceFingerprint.getStoredDeviceId();
};

# 2. 主要增强点

  • 增强硬件特征:

    • WebGL供应商和渲染器信息(直接反映GPU硬件)
    • 音频上下文信息(声卡硬件相关)
    • 设备像素比(显示器硬件特征)
    • 性能特征(CPU处理速度差异)
  • 增加更多维度:

    • WebGL扩展列表(不同GPU支持不同扩展)
    • 媒体设备信息(摄像头、麦克风硬件)
    • 电池信息(移动设备特征)
    • 网络连接信息
  • 改进算法:

    • 更复杂的哈希算法
    • 添加随机熵避免碰撞
    • 使用更多硬件相关特征生成UUID
  • 增强图形测试:

    • 复杂的Canvas绘制(测试GPU渲染差异)
    • 渐变、阴影等GPU加速效果

这样即使两台电脑有相同的软件配置,但由于硬件差异(不同GPU、声卡、CPU性能等),生成的指纹也会有很大差异,大大降低了碰撞概率。

# 三、硬件指纹

# 1. 实现代码

devicefingeruuid.1.0.3.js

/**
 * 设备指纹识别 - 基于硬件特征的稳定deviceId
 * 同一设备不同浏览器生成相同指纹,删除后能恢复
 * @version 1.0.3
 */

class DeviceFingerprint {
    constructor() {
        this.storageKey = 'device_fingerprint_uuid';
        this.localStorageKey = 'device_fp_data';
        this.fingerprintData = null;
    }

    /**
     * 初始化设备指纹
     * @returns {Promise<string>} deviceId
     */
    async init() {
        try {
            // 1. 首先尝试从本地存储获取
            let deviceId = this.getStoredDeviceId();
            if (deviceId) {
                console.log('从存储中获取到deviceId:', deviceId);
                this.updateLastAccessed();
                return deviceId;
            }

            // 2. 生成硬件特征指纹
            const hardwareFingerprint = await this.generateHardwareFingerprint();
            
            // 3. 基于硬件特征生成稳定UUID
            deviceId = this.generateHardwareUUID(hardwareFingerprint);
            
            console.log('基于硬件特征生成deviceId:', deviceId);
            
            // 4. 存储指纹数据
            this.storeFingerprintData(hardwareFingerprint, deviceId);
            
            return deviceId;
            
        } catch (error) {
            console.error('设备指纹生成失败:', error);
            return this.generateFallbackUUID();
        }
    }

    /**
     * 生成硬件特征指纹(跨浏览器稳定)
     * @returns {Promise<Object>}
     */
    async generateHardwareFingerprint() {
        const fingerprint = {
            // 屏幕硬件特征(跨浏览器一致)
            screen: {
                width: screen.width,
                height: screen.height,
                colorDepth: screen.colorDepth,
                pixelDepth: screen.pixelDepth,
                availWidth: screen.availWidth,
                availHeight: screen.availHeight
            },
            
            // GPU硬件特征(最重要的区分因素)
            gpu: {
                vendor: await this.getGPUInfo().vendor,
                renderer: await this.getGPUInfo().renderer,
                extensions: await this.getGPUInfo().extensions
            },
            
            // CPU硬件特征
            cpu: {
                cores: navigator.hardwareConcurrency || 0,
                memory: navigator.deviceMemory || 0
            },
            
            // 音频硬件特征
            audio: {
                sampleRate: await this.getAudioHardwareInfo()
            },
            
            // 设备类型特征
            device: {
                type: this.getDeviceType(),
                pixelRatio: window.devicePixelRatio || 1,
                touchSupport: this.hasTouchSupport()
            },
            
            // 时区(硬件位置相关)
            location: {
                timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
                offset: new Date().getTimezoneOffset()
            }
        };

        return fingerprint;
    }

    /**
     * 获取GPU硬件信息(跨浏览器)
     * @returns {Promise<Object>}
     */
    async getGPUInfo() {
        try {
            const canvas = document.createElement('canvas');
            const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
            
            if (!gl) {
                return { vendor: 'no_webgl', renderer: 'no_webgl', extensions: 'no_webgl' };
            }
            
            // 获取WebGL渲染器信息(直接反映GPU硬件)
            const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
            let vendor = 'unknown';
            let renderer = 'unknown';
            
            if (debugInfo) {
                vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || 'unknown';
                renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || 'unknown';
            } else {
                vendor = gl.getParameter(gl.VENDOR) || 'unknown';
                renderer = gl.getParameter(gl.RENDERER) || 'unknown';
            }
            
            // 获取支持的扩展
            const extensions = gl.getSupportedExtensions() || [];
            
            return {
                vendor: this.normalizeGPUString(vendor),
                renderer: this.normalizeGPUString(renderer),
                extensions: extensions.sort().join(',')
            };
            
        } catch (error) {
            return { vendor: 'error', renderer: 'error', extensions: 'error' };
        }
    }

    /**
     * 标准化GPU字符串
     * @param {string} str 
     * @returns {string}
     */
    normalizeGPUString(str) {
        return str.toLowerCase()
            .replace(/corporation/gi, '')
            .replace(/inc/gi, '')
            .replace(/llc/gi, '')
            .replace(/\(/g, '')
            .replace(/\)/g, '')
            .replace(/\s+/g, ' ')
            .trim();
    }

    /**
     * 获取音频硬件信息
     * @returns {Promise<number>}
     */
    async getAudioHardwareInfo() {
        try {
            const audioContext = new (window.AudioContext || window.webkitAudioContext)();
            const sampleRate = audioContext.sampleRate;
            audioContext.close();
            return sampleRate;
        } catch (error) {
            return 0;
        }
    }

    /**
     * 获取设备类型
     * @returns {string}
     */
    getDeviceType() {
        const userAgent = navigator.userAgent.toLowerCase();
        const screenWidth = screen.width;
        const screenHeight = screen.height;
        
        if (userAgent.includes('mobile') || userAgent.includes('android') || userAgent.includes('iphone')) {
            return 'mobile';
        } else if (screenWidth < 768 || screenHeight < 768) {
            return 'tablet';
        } else {
            return 'desktop';
        }
    }

    /**
     * 检查触摸支持
     * @returns {boolean}
     */
    hasTouchSupport() {
        return 'ontouchstart' in window || 
               navigator.maxTouchPoints > 0 || 
               navigator.msMaxTouchPoints > 0;
    }

    /**
     * 基于硬件特征生成稳定UUID
     * @param {Object} hardwareFingerprint 
     * @returns {string}
     */
    generateHardwareUUID(hardwareFingerprint) {
        // 使用最稳定的硬件特征生成UUID
        const hardwareSignature = [
            // GPU信息(最稳定)
            hardwareFingerprint.gpu.vendor,
            hardwareFingerprint.gpu.renderer,
            
            // 屏幕信息
            hardwareFingerprint.screen.width,
            hardwareFingerprint.screen.height,
            hardwareFingerprint.screen.colorDepth,
            
            // CPU信息
            hardwareFingerprint.cpu.cores,
            hardwareFingerprint.cpu.memory,
            
            // 音频硬件
            hardwareFingerprint.audio.sampleRate,
            
            // 设备特征
            hardwareFingerprint.device.type,
            hardwareFingerprint.device.pixelRatio,
            
            // 位置信息
            hardwareFingerprint.location.timezone
        ].join('|');
        
        // 使用稳定的哈希算法
        let hash = 0;
        for (let i = 0; i < hardwareSignature.length; i++) {
            const char = hardwareSignature.charCodeAt(i);
            hash = ((hash << 5) - hash) + char;
            hash = hash & 0x7FFFFFFF; // 确保是正数
        }
        
        // 生成UUID v4格式,但基于硬件特征
        const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
        let result = '';
        
        for (let i = 0; i < template.length; i++) {
            const c = template[i];
            if (c === 'x') {
                // 使用硬件哈希
                const r = (hash + i * 13) % 16;
                hash = Math.floor(hash / 16);
                result += r.toString(16);
            } else if (c === 'y') {
                // 固定版本位
                result += '8';
            } else {
                result += c;
            }
        }
        
        return result;
    }

    /**
     * 从本地存储获取deviceId
     * @returns {string|null}
     */
    getStoredDeviceId() {
        try {
            // 优先从localStorage获取
            if (typeof localStorage !== 'undefined') {
                const stored = localStorage.getItem(this.storageKey);
                if (stored) {
                    return stored;
                }
            }
            
            // 其次从sessionStorage获取
            if (typeof sessionStorage !== 'undefined') {
                const stored = sessionStorage.getItem(this.storageKey);
                if (stored) {
                    return stored;
                }
            }
            
            return null;
        } catch (error) {
            console.warn('读取存储失败:', error);
            return null;
        }
    }

    /**
     * 存储设备指纹数据
     * @param {Object} fingerprint 
     * @param {string} deviceId 
     */
    storeFingerprintData(fingerprint, deviceId) {
        try {
            // 存储deviceId
            if (typeof localStorage !== 'undefined') {
                localStorage.setItem(this.storageKey, deviceId);
            }
            if (typeof sessionStorage !== 'undefined') {
                sessionStorage.setItem(this.storageKey, deviceId);
            }
            
            // 存储完整的硬件指纹数据
            const storageData = {
                deviceId: deviceId,
                hardwareFingerprint: fingerprint,
                createdAt: new Date().toISOString(),
                lastAccessed: new Date().toISOString()
            };
            
            if (typeof localStorage !== 'undefined') {
                localStorage.setItem(this.localStorageKey, JSON.stringify(storageData));
            }
            
        } catch (error) {
            console.warn('存储设备指纹数据失败:', error);
        }
    }

    /**
     * 更新最后访问时间
     */
    updateLastAccessed() {
        try {
            if (typeof localStorage !== 'undefined') {
                const storedData = localStorage.getItem(this.localStorageKey);
                if (storedData) {
                    const data = JSON.parse(storedData);
                    data.lastAccessed = new Date().toISOString();
                    localStorage.setItem(this.localStorageKey, JSON.stringify(data));
                }
            }
        } catch (error) {
            console.warn('更新最后访问时间失败:', error);
        }
    }

    /**
     * 降级方案:生成随机UUID
     * @returns {string}
     */
    generateFallbackUUID() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            const r = Math.random() * 16 | 0;
            return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        });
    }

    /**
     * 获取设备信息摘要
     * @returns {Object}
     */
    getDeviceInfo() {
        return {
            deviceId: this.getStoredDeviceId(),
            screen: `${screen.width}x${screen.height}`,
            gpu: navigator.gpu ? 'supported' : 'not_supported',
            cores: navigator.hardwareConcurrency || 'unknown',
            type: this.getDeviceType()
        };
    }

    /**
     * 清除设备指纹数据
     */
    clear() {
        try {
            if (typeof localStorage !== 'undefined') {
                localStorage.removeItem(this.storageKey);
                localStorage.removeItem(this.localStorageKey);
            }
            if (typeof sessionStorage !== 'undefined') {
                sessionStorage.removeItem(this.storageKey);
            }
            console.log('设备指纹数据已清除');
        } catch (error) {
            console.error('清除设备指纹数据失败:', error);
        }
    }

    /**
     * 验证指纹稳定性(调试用)
     * @returns {Promise<boolean>}
     */
    async verifyStability() {
        try {
            const currentFingerprint = await this.generateHardwareFingerprint();
            const storedData = localStorage.getItem(this.localStorageKey);
            
            if (!storedData) return false;
            
            const historyData = JSON.parse(storedData);
            const historyFingerprint = historyData.hardwareFingerprint;
            
            // 比较关键硬件特征
            const keyFeatures = [
                'gpu.vendor', 'gpu.renderer', 
                'screen.width', 'screen.height',
                'cpu.cores', 'audio.sampleRate'
            ];
            
            let matchCount = 0;
            for (const feature of keyFeatures) {
                const [category, prop] = feature.split('.');
                const current = currentFingerprint[category][prop];
                const history = historyFingerprint[category][prop];
                
                if (current === history) {
                    matchCount++;
                }
            }
            
            const stability = matchCount / keyFeatures.length;
            console.log(`指纹稳定性: ${(stability * 100).toFixed(1)}%`);
            
            return stability >= 0.8;
        } catch (error) {
            console.error('稳定性验证失败:', error);
            return false;
        }
    }
}

// 创建全局实例
const deviceFingerprint = new DeviceFingerprint();

// 导出给其他模块使用
if (typeof module !== 'undefined' && module.exports) {
    module.exports = deviceFingerprint;
} else {
    window.deviceFingerprint = deviceFingerprint;
}

/**
 * 自动初始化设备指纹
 */
document.addEventListener('DOMContentLoaded', async function() {
    try {
        const deviceId = await deviceFingerprint.init();
        
        // 将deviceId设置为全局变量
        window.deviceId = deviceId;
        
        // 触发自定义事件
        const event = new CustomEvent('deviceIdReady', {
            detail: { deviceId: deviceId }
        });
        document.dispatchEvent(event);
        
        console.log('设备指纹初始化完成:', deviceId);
        
        // 验证稳定性(调试)
        setTimeout(() => {
            deviceFingerprint.verifyStability();
        }, 1000);
        
    } catch (error) {
        console.error('设备指纹初始化失败:', error);
    }
});

// 提供简单的API接口
window.getDeviceId = function() {
    return window.deviceId || deviceFingerprint.getStoredDeviceId();
};

# 2. 说明

  1. 专注于硬件特征:
  • GPU供应商和渲染器(最稳定)

  • 屏幕物理尺寸和色深

  • CPU核心数和内存

  • 音频硬件采样率

  • 设备像素比

  1. 跨浏览器一致性:
  • 移除浏览器特定信息(userAgent等)

  • 使用WebGL获取真实GPU信息

  • 标准化硬件字符串

  1. 稳定哈希算法:
  • 只使用硬件特征生成UUID

  • 避免时间戳等不稳定因素

  • 确保同一设备不同浏览器生成相同指纹

  1. 验证机制:
  • 提供稳定性验证功能

  • 调试信息输出

# 四、使用示例

# 1. 在html中的使用

在HTML中(或前端项目中)引入并使用:

<script src="/public/xxx/devicefingeruuid.js"></script>
<script>
// 方式1:监听自定义事件
document.addEventListener('deviceIdReady', function(event) {
    const deviceId = event.detail.deviceId;
    console.log('设备ID已就绪:', deviceId);
    
    // 在这里使用deviceId,比如发送到服务器
    // sendDeviceIdToServer(deviceId);
});

// 方式2:直接获取(确保在DOMContentLoaded之后)
document.addEventListener('DOMContentLoaded', function() {
    const deviceId = window.getDeviceId();
    if (deviceId) {
        console.log('当前设备ID:', deviceId);
    }
});

// 方式3:在用户操作时获取
function getUserDeviceId() {
    return window.getDeviceId() || 'unknown';
}
</script>
更新时间: 2025年11月16日星期日上午11点26分