saas建站,云主机做网站,网站设计流程的步骤,网站建设的发展历程大家好#xff0c;我是石小石#xff0c;一个热爱技术分享的开源社区贡献者。写有《油猴脚本实战指南》、《Vite极速入门与进阶》、《Threejs极速入门》、《前端学Java》等专栏。目前专注于微前端架构与 AI 相关技术的研究与工程实践。
什么是浏览器指纹#xff1f;
浏览器…大家好我是石小石一个热爱技术分享的开源社区贡献者。写有《油猴脚本实战指南》、《Vite极速入门与进阶》、《Threejs极速入门》、《前端学Java》等专栏。目前专注于微前端架构与 AI 相关技术的研究与工程实践。
什么是浏览器指纹
浏览器指纹Browser Fingerprinting顾名思义是用来唯一标识你浏览器的一组“特征值”。它不是我们理解中的那种真实指纹而是通过收集浏览器、操作系统、设备分辨率、字体、插件等信息组合成的一个独特 ID。
和传统的 Cookie 不同浏览器指纹不需要在用户设备上存储任何东西完全是“读取现有信息”来识别用户。
使用背景
在最近的项目中有个小需求想用用户的设备作为唯一凭证来验证身份。
一开始我想着简单粗暴点用 JS 获取手机的 IMEI 或 PC 的序列号。但查了下资料后才发现这根本行不通——JS 根本没权限访问这些底层硬件信息安全机制早就把这条路堵死了。
后来才反应过来我真正想要的是一个“设备唯一标识”也就是——浏览器指纹。
可行方案
查阅了一些资料之后目前比较常见的几种浏览器指纹方案如下
Navigator 指纹浏览器类型、版本、系统平台等信息。Canvas 指纹让浏览器绘制一段隐藏的图像然后读取图像的像素差异不同设备会有微小区别。WebGL 指纹利用显卡和图形驱动渲染差异获取设备的唯一特征。字体、插件、时区、屏幕分辨率等这些信息组合起来也能提供一定的识别度。
当然单一方案识别率可能不高但多种信息结合后指纹的唯一性就会明显提升。
Navigator 指纹
Navigator 是前端获取浏览器和部分设备环境信息的重要接口。
下面是一些常用的属性和方法跨浏览器兼容性较好的为主
属性/方法作用说明示例代码font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.userAgent/font获取浏览器的用户代理字符串可以用于判断浏览器类型、系统类型font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.userAgent/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.platform/font获取运行环境的操作系统平台类型如 Win32、Linux x86_64、MacIntelfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.platform/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.appVersion/font获取浏览器版本信息和部分平台信息font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.appVersion/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.appName/font获取浏览器名称大多数现代浏览器返回 “Netscape”font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.appName/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.language/font返回当前浏览器的首选语言如 “zh-CN”、“en-US”font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.language/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.languages/font返回用户的首选语言列表font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.languages/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.hardwareConcurrency/font返回可用的逻辑处理器数量CPU核心数font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.hardwareConcurrency/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.plugins/font返回当前安装的插件列表仅桌面浏览器有意义且有兼容性限制font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.plugins/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.onLine/font判断当前浏览器是否联网font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.onLine/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.cookieEnabled/font判断浏览器是否启用 Cookiefont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.cookieEnabled/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.geolocation/font提供地理位置定位服务需要用户授权font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.geolocation.getCurrentPosition(...)/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.maxTouchPoints/font支持的最大触控点个数触屏设备可用font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.maxTouchPoints/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.mediaDevices/font访问音视频设备管理 API如获取麦克风、摄像头font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.mediaDevices.getUserMedia(...)/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.clipboard/font读写系统剪贴板部分浏览器需要 https 环境和权限font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.clipboard.writeText(Hello)/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.connection/font获取网络连接信息对象如带宽、类型部分浏览器支持font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.connection.effectiveType/fontfont stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.userAgentData/font在新标准中可用的一种用户代理信息对象部分浏览器已支持用户隐私性更高font stylecolor:rgb(71, 101, 130);background-color:rgba(27, 31, 35, 0.05);navigator.userAgentData/font
偷个懒让Tare直接帮我写个Navigator 指纹示例吧。 !DOCTYPE html
htmlheadtitleNavigator 指纹示例/title
/headbodyh2Navigator 指纹示例/h2pre idoutput/prescriptasync function getNavigatorFingerprint() {// 收集 navigator 相关信息const data {userAgent: navigator.userAgent,platform: navigator.platform,language: navigator.language,languages: navigator.languages,cookieEnabled: navigator.cookieEnabled,hardwareConcurrency: navigator.hardwareConcurrency || N/A,deviceMemory: navigator.deviceMemory || N/A,webdriver: navigator.webdriver || false,};// 将数据转成字符串const dataString JSON.stringify(data);// 计算 SHA-256 哈希const hashBuffer await crypto.subtle.digest(SHA-256,new TextEncoder().encode(dataString));// 转成十六进制字符串const hashArray Array.from(new Uint8Array(hashBuffer));const hashHex hashArray.map(b b.toString(16).padStart(2, 0)).join();return { data, fingerprint: hashHex };}getNavigatorFingerprint().then(result {const output document.getElementById(output);output.textContent 采集到的 Navigator 信息:\n JSON.stringify(result.data, null, 2) \n\n生成的指纹SHA-256:\n result.fingerprint;});/script
/body/html代码生成完毕点击应用直接预览 经过测试在同一个电脑上这个指纹是稳定的多次执行这个值不会变。
但这这个指纹明显有缺陷我系统语言或者浏览器升级后这个指纹肯定会改变。
Canvas 指纹
由于不同设备包括操作系统、显卡、驱动、字体渲染引擎等在绘制同一段 Canvas 内容时会存在细微差异最终得到的图像数据通常是像素或转成 base64在不同设备上往往是不同的。
这些细微差异生成的哈希值就是“指纹”由于只与设备性能有关指纹稳定性显然比Navigator 指纹高一些。 !DOCTYPE html
html
headtitle简单Canvas指纹示例/title
/head
bodyh2简单Canvas指纹示例/h2p请打开控制台(F12)查看结果/pscript// 创建一个简单的Canvas指纹生成函数function generateCanvasFingerprint() {// 创建canvas元素const canvas document.createElement(canvas);canvas.width 200;canvas.height 100;// 获取绘图上下文const ctx canvas.getContext(2d);// 填充背景ctx.fillStyle white;ctx.fillRect(0, 0, canvas.width, canvas.height);// 绘制一些图形和文字// 绘制红色矩形ctx.fillStyle red;ctx.fillRect(20, 20, 50, 50);// 绘制蓝色圆形ctx.fillStyle blue;ctx.beginPath();ctx.arc(120, 45, 25, 0, Math.PI * 2);ctx.fill();// 绘制文本ctx.fillStyle black;ctx.font 16px Arial;ctx.fillText(Canvas指纹, 60, 80);// 获取canvas数据URLconst dataURL canvas.toDataURL();// 简单哈希函数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; // 转换为32位整数}return hash.toString(16); // 转换为16进制}// 计算指纹const fingerprint simpleHash(dataURL);return {fingerprint: fingerprint,dataURL: dataURL};}// 生成并输出指纹const result generateCanvasFingerprint();console.log(Canvas指纹:, result.fingerprint);console.log(Canvas数据URL前100个字符:, result.dataURL.substring(0, 100) ...);// 如果浏览器支持更安全的哈希算法也可以使用它if (window.crypto window.crypto.subtle) {const encoder new TextEncoder();const data encoder.encode(result.dataURL);window.crypto.subtle.digest(SHA-256, data).then(hashBuffer {// 将哈希缓冲区转换为十六进制字符串const hashArray Array.from(new Uint8Array(hashBuffer));const hashHex hashArray.map(b b.toString(16).padStart(2, 0)).join();console.log(Canvas指纹(SHA-256):, hashHex);});}/script
/body
/html生成的指纹还是很不错的。 其他几种方式生成浏览器指纹都大同小异这里就不介绍了。