browser-canvas-fingerprinting
Version:
A simple canvas fingerprinting implementation in browser with specific information used to generate fingerprint
344 lines (300 loc) • 11.4 kB
HTML
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas 指纹识别演示</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
color: #333;
}
.container {
max-width: 800px;
width: 100%;
background: white;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
header {
background: #4a6fa5;
color: white;
padding: 25px;
text-align: center;
}
h1 {
font-size: 28px;
margin-bottom: 10px;
}
.subtitle {
font-size: 16px;
opacity: 0.9;
}
.content {
padding: 30px;
}
.description {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
margin-bottom: 25px;
line-height: 1.6;
border-left: 4px solid #4a6fa5;
}
.options {
display: flex;
gap: 15px;
margin-bottom: 25px;
flex-wrap: wrap;
}
button {
flex: 1;
min-width: 200px;
padding: 15px;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.btn-hash {
background: #4a6fa5;
color: white;
}
.btn-hash:hover {
background: #3a5a8a;
transform: translateY(-2px);
}
.btn-canvas {
background: #e9ecef;
color: #333;
}
.btn-canvas:hover {
background: #dee2e6;
transform: translateY(-2px);
}
.result-area {
margin-top: 25px;
display: none;
}
.result-title {
font-size: 18px;
margin-bottom: 15px;
color: #4a6fa5;
display: flex;
align-items: center;
gap: 10px;
}
.hash-result {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
font-family: monospace;
word-break: break-all;
border: 1px solid #e9ecef;
}
.canvas-container {
text-align: center;
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #e9ecef;
}
canvas {
max-width: 100%;
border: 1px solid #ddd;
border-radius: 4px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.privacy-notice {
background: #fff3cd;
border: 1px solid #ffeaa7;
border-radius: 8px;
padding: 15px;
margin-top: 25px;
font-size: 14px;
color: #856404;
}
.loading {
display: none;
text-align: center;
padding: 20px;
}
.spinner {
border: 4px solid rgba(0, 0, 0, 0.1);
border-left-color: #4a6fa5;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 0 auto 10px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
footer {
text-align: center;
padding: 20px;
font-size: 14px;
color: #6c757d;
border-top: 1px solid #e9ecef;
}
@media (max-width: 600px) {
.options {
flex-direction: column;
}
button {
min-width: 100%;
}
}
#extensionTip {
color: red;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>Canvas 指纹识别演示</h1>
<p class="subtitle">了解浏览器指纹识别技术的工作原理</p>
<div id="extensionTip"></div>
</header>
<div class="content">
<div class="description">
<p>Canvas 指纹识别是一种通过检测浏览器渲染图形时的微小差异来生成唯一标识符的技术。</p>
<p>此演示展示了如何通过 Canvas 元素生成浏览器指纹。选择下面的选项来查看不同的输出结果。</p>
</div>
<div class="options">
<button class="btn-hash" id="hashBtn">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"></path>
</svg>
生成指纹哈希
</button>
<button class="btn-canvas" id="canvasBtn">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<line x1="9" y1="3" x2="9" y2="21"></line>
</svg>
显示Canvas图像
</button>
</div>
<div class="loading" id="loading">
<div class="spinner"></div>
<p>正在生成指纹,请稍候...</p>
</div>
<div class="result-area" id="hashResult">
<h3 class="result-title">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"></path>
</svg>
您的Canvas指纹哈希值
</h3>
<div class="hash-result" id="hashValue"></div>
</div>
<div class="result-area" id="canvasResult">
<h3 class="result-title">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<line x1="9" y1="3" x2="9" y2="21"></line>
</svg>
Canvas渲染结果
</h3>
<div class="canvas-container">
<canvas id="fingerprintCanvas"></canvas>
</div>
</div>
<div class="privacy-notice">
<p><strong>隐私提示:</strong> Canvas指纹识别是一种隐蔽的跟踪技术。虽然此演示仅用于教育目的,但在实际网站中,此类技术可能被用于跟踪用户行为。建议使用隐私保护工具(如Brave浏览器或Firefox的严格跟踪保护)来防范此类跟踪。</p>
</div>
</div>
<footer>
</footer>
</div>
<script type="module">
// 导入指纹识别模块
import fingerprint from '../dist/main.min.js';
import { isExtensionFuckingCanvas } from '../dist/main.min.js';
// 获取DOM元素
const hashBtn = document.getElementById('hashBtn');
const canvasBtn = document.getElementById('canvasBtn');
const loading = document.getElementById('loading');
const hashResult = document.getElementById('hashResult');
const canvasResult = document.getElementById('canvasResult');
const hashValue = document.getElementById('hashValue');
const fingerprintCanvas = document.getElementById('fingerprintCanvas');
isExtensionFuckingCanvas().then(r => {
if (r) extensionTip.innerText = "WARNING: Canvas has been fucked by browser extension";
})
// 生成哈希按钮点击事件
hashBtn.addEventListener('click', async () => {
// 显示加载状态
loading.style.display = 'block';
hashResult.style.display = 'none';
canvasResult.style.display = 'none';
try {
// 调用指纹函数,获取哈希值
const hash = await fingerprint();
// 显示结果
hashValue.textContent = hash;
hashResult.style.display = 'block';
} catch (error) {
console.error('生成指纹时出错:', error);
hashValue.textContent = '错误: ' + error.message;
hashResult.style.display = 'block';
} finally {
// 隐藏加载状态
loading.style.display = 'none';
}
});
// 显示Canvas按钮点击事件
canvasBtn.addEventListener('click', async () => {
// 显示加载状态
loading.style.display = 'block';
hashResult.style.display = 'none';
canvasResult.style.display = 'none';
try {
// 调用指纹函数,获取Canvas元素
const canvas = await fingerprint('', 2);
// 清空并设置Canvas尺寸
fingerprintCanvas.width = canvas.width;
fingerprintCanvas.height = canvas.height;
// 将Canvas内容绘制到显示Canvas上
const ctx = fingerprintCanvas.getContext('2d');
ctx.drawImage(canvas, 0, 0);
// 显示结果
canvasResult.style.display = 'block';
} catch (error) {
console.error('生成Canvas时出错:', error);
const ctx = fingerprintCanvas.getContext('2d');
ctx.fillStyle = '#f8f9fa';
ctx.fillRect(0, 0, fingerprintCanvas.width, fingerprintCanvas.height);
ctx.fillStyle = '#dc3545';
ctx.font = '12px Arial';
ctx.fillText('错误: ' + error.message, 10, 30);
canvasResult.style.display = 'block';
} finally {
// 隐藏加载状态
loading.style.display = 'none';
}
});
</script>
</body>
</html>