JavaScript获取浏览器指纹

首次发布:2025-12-18
<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript获取浏览器指纹</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 960px;
            margin: 0 auto;
            padding: 20px;
            line-height: 1.6;
        }

        .card {
            background: #f5f5f5;
            border-radius: 8px;
            padding: 20px;
            margin: 20px 0;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }

        .fingerprint-item {
            margin: 10px 0;
            padding: 10px;
            background: white;
            border-radius: 4px;
            display: flex;
            justify-content: space-between;
        }

              .hash {
            font-family: monospace;
            color: #2196F3;
            font-weight: bold;
            word-break: break-all;
        }
   
        .info {
            color: #666;
            font-size: 14px;
            margin-top: 5px;
        }
    </style>
</head>

<body>
    <h1>JavaScript获取浏览器指纹</h1>


    <div class="card">
        <h2>指纹信息</h2>
        <div id="fingerprints"></div>
    </div>


    <script>
        // 简单的哈希函数(实际项目中应该使用更强大的哈希算法)
        function simpleHash(str) {
            let hash = 0;
            for (let i = 0; i < str.length; i++) {
                const char = str.charCodeAt(i);
                hash = ((hash << 5) - hash) + char;
                hash = hash & hash;
            }
            return Math.abs(hash).toString(16).toUpperCase();
        }

        // 1. 获取Canvas指纹
        function getCanvasFingerprint() {
            try {
                const canvas = document.createElement('canvas');
                canvas.width = 200;
                canvas.height = 50;
                const ctx = canvas.getContext('2d');

                // 绘制一些文本和图形
                ctx.textBaseline = 'top';
                ctx.font = '14px Arial';
                ctx.fillStyle = '#f60';
                ctx.fillRect(0, 0, 100, 50);

                ctx.fillStyle = '#069';
                ctx.fillText('Browser Fingerprint', 2, 15);

                // 添加一些复杂的渲染
                ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
                ctx.fillRect(50, 10, 60, 30);

                // 转换为数据URL并哈希
                const dataUrl = canvas.toDataURL();
                return simpleHash(dataUrl);
            } catch (e) {
                return 'ERROR:' + simpleHash(e.message);
            }
        }

        // 2. 获取WebGL指纹
        function getWebGLFingerprint() {
            try {
                const canvas = document.createElement('canvas');
                const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');

                if (!gl) {
                    return 'WebGL not supported';
                }

                // 获取WebGL渲染器信息
                const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
                let renderer = 'Unknown';
                let vendor = 'Unknown';

                if (debugInfo) {
                    renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
                    vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
                }

                // 获取WebGL版本和更多参数
                const params = [
                    gl.VERSION,
                    gl.SHADING_LANGUAGE_VERSION,
                    gl.VENDOR,
                    gl.RENDERER,
                    gl.getParameter(gl.MAX_TEXTURE_SIZE),
                    gl.getParameter(gl.MAX_RENDERBUFFER_SIZE)
                ];

                return simpleHash(params.join('|') + renderer + vendor);
            } catch (e) {
                return 'ERROR:' + simpleHash(e.message);
            }
        }

        // 3. 获取字体指纹(简化版)
        function getFontsFingerprint() {
            try {
                // 检查一组常用字体
                const fontList = [
                    'Arial', 'Arial Black', 'Courier New', 'Times New Roman',
                    'Georgia', 'Verdana', 'Tahoma', 'Trebuchet MS',
                    'Impact', 'Comic Sans MS', 'Microsoft YaHei',
                    'SimSun', 'SimHei', 'KaiTi', 'FangSong'
                ];

                const availableFonts = [];
                const testString = "mmmmmmmmmmlli";
                const testSize = '72px';

                // 创建测试元素
                const span = document.createElement('span');
                span.style.fontSize = testSize;
                span.innerHTML = testString;
                document.body.appendChild(span);

                // 获取默认字体的宽度
                span.style.fontFamily = 'monospace';
                const defaultWidth = span.offsetWidth;

                // 测试每个字体
                fontList.forEach(font => {
                    span.style.fontFamily = `'${font}', monospace`;
                    if (span.offsetWidth !== defaultWidth) {
                        availableFonts.push(font);
                    }
                });

                document.body.removeChild(span);
                return simpleHash(availableFonts.join(','));
            } catch (e) {
                return 'ERROR:' + simpleHash(e.message);
            }
        }

        // 4. 获取音频指纹
        function getAudioFingerprint() {
            return new Promise((resolve) => {
                try {
                    if (!window.AudioContext && !window.webkitAudioContext) {
                        resolve('AudioContext not supported');
                        return;
                    }

                    const audioContext = new (window.AudioContext || window.webkitAudioContext)();
                    const oscillator = audioContext.createOscillator();
                    const gainNode = audioContext.createGain();

                    oscillator.connect(gainNode);
                    gainNode.connect(audioContext.destination);

                    oscillator.type = 'sine';
                    oscillator.frequency.value = 1000;

                    gainNode.gain.value = 0;

                    // 获取音频处理的指纹
                    const fingerprintData = [
                        audioContext.sampleRate,
                        audioContext.destination.channelCount,
                        audioContext.currentTime,
                        navigator.hardwareConcurrency || 'unknown'
                    ].join('|');

                    oscillator.start();
                    setTimeout(() => {
                        oscillator.stop();
                        audioContext.close();
                        resolve(simpleHash(fingerprintData));
                    }, 100);
                } catch (e) {
                    resolve('ERROR:' + simpleHash(e.message));
                }
            });
        }

        // 5. 获取综合指纹
        async function getCompositeFingerprint() {
            const components = [
                navigator.userAgent,
                navigator.platform,
                navigator.language,
                navigator.languages ? navigator.languages.join(',') : '',
                screen.width + 'x' + screen.height + 'x' + screen.colorDepth,
                new Date().getTimezoneOffset(),
                navigator.hardwareConcurrency || 'unknown',
                navigator.deviceMemory || 'unknown',
                window.devicePixelRatio || 'unknown',
                // 排除canvas和webgl,因为它们已经是独立的指纹
            ].join('|');

            return simpleHash(components);
        }

        // 6. 主函数:获取所有指纹
        async function getFingerprint() {
            const fingerprintsDiv = document.getElementById('fingerprints');
            fingerprintsDiv.innerHTML = '<p>正在计算指纹...</p>';

            try {
                // 获取各种指纹
                const canvasFP = getCanvasFingerprint();
                const webglFP = getWebGLFingerprint();
                const fontsFP = getFontsFingerprint();
                const audioFP = await getAudioFingerprint();
                const compositeFP = await getCompositeFingerprint();

                // 显示结果
                fingerprintsDiv.innerHTML = `
                    <div class="fingerprint-item">
                        <span>Canvas 画布指纹:</span>
                        <span class="hash">${canvasFP}</span>
                    </div>
                    <div class="fingerprint-item">
                        <span>WebGL 图形指纹:</span>
                        <span class="hash">${webglFP}</span>
                    </div>
                    <div class="fingerprint-item">
                        <span>字体指纹:</span>
                        <span class="hash">${fontsFP}</span>
                    </div>
                    <div class="fingerprint-item">
                        <span>音频指纹:</span>
                        <span class="hash">${audioFP}</span>
                    </div>
                    <div class="fingerprint-item">
                        <span>综合浏览器指纹:</span>
                        <span class="hash">${compositeFP}</span>
                    </div>
                   
                    <div class="fingerprint-item">
                        <span>完整指纹哈希:</span>
                        <span class="hash">${simpleHash(canvasFP + webglFP + fontsFP + audioFP + compositeFP)}</span>
                    </div>
                `;

                document.removeEventListener('click', getFingerprint);
                document.removeEventListener('keydown', getFingerprint);
                document.removeEventListener('touchstart', getFingerprint);
                document.removeEventListener('focus', getFingerprint);
                document.removeEventListener('blur', getFingerprint);
                document.removeEventListener('mouseenter', getFingerprint);
                document.removeEventListener('mouseleave', getFingerprint);
                document.removeEventListener('touchmove', getFingerprint);
                document.removeEventListener('touchend', getFingerprint);
                document.removeEventListener('touchcancel', getFingerprint);

            } catch (error) {
                fingerprintsDiv.innerHTML = `<p style="color: red;">获取指纹时出错: ${error.message}</p>`;
            }
        }

        // 监听多种用户交互事件
        document.addEventListener('click', getFingerprint);
        document.addEventListener('keydown', getFingerprint);
        // 触摸事件
        document.addEventListener('touchstart', getFingerprint);
        // 页面获得/失去焦点
        window.addEventListener('focus', getFingerprint);
        window.addEventListener('blur', getFingerprint);
        // 鼠标进入/离开
        document.addEventListener('mouseenter', getFingerprint);
        document.addEventListener('mouseleave', getFingerprint);
        // 手指在屏幕上移动
        document.addEventListener('touchmove', getFingerprint);

        // 手指离开屏幕
        document.addEventListener('touchend', getFingerprint);

        // 触摸被取消(如来电中断)
        document.addEventListener('touchcancel', getFingerprint);
        
        //鼠标移动
        // document.addEventListener('mousemove', getFingerprint);
        // document.addEventListener('mousemove', (event) => {
        //     console.log('鼠标移动:', {
        //         x: event.clientX,    // 相对于浏览器窗口的X坐标
        //         y: event.clientY,    // 相对于浏览器窗口的Y坐标
        //         pageX: event.pageX,  // 相对于文档的X坐标
        //         pageY: event.pageY,  // 相对于文档的Y坐标
        //         screenX: event.screenX, // 相对于屏幕的X坐标
        //         screenY: event.screenY  // 相对于屏幕的Y坐标
        //     });
        // });
    </script>
</body>

</html>

本文来自www.luofenming.com