<!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