基于设备指纹识别的反爬虫技术:给设备办 “身份证”
传统的封禁 IP、验证码等反爬虫手段已逐渐失效,基于设备指纹识别的反爬虫技术应运而生,成为守护数据安全的新防线。它如同给每个设备办一张独一无二的 “身份证”,精准区分正常用户与爬虫工具。
一、基础参数采集:构建设备指纹的 “骨架”
设备指纹的基础参数采集,是构建设备指纹的第一步,主要收集设备的浏览器信息、操作系统、屏幕特性等相对稳定的特征,为后续生成唯一标识奠定基础。
浏览器与操作系统信息
通过 navigator.userAgent
可获取浏览器的名称、版本以及操作系统的类型和版本等信息。这一参数能让我们初步了解用户的设备环境,例如是使用 Chrome 浏览器还是 Firefox 浏览器,操作系统是 Windows 还是 macOS。
// 获取浏览器和操作系统信息
const getBrowserAndOSInfo = () => {const userAgent = navigator.userAgent;// 对 userAgent 字符串进行简单解析,获取浏览器和操作系统信息let browserName = 'Unknown';let osName = 'Unknown';if (userAgent.indexOf('Chrome') > -1) {browserName = 'Chrome';} else if (userAgent.indexOf('Firefox') > -1) {browserName = 'Firefox';}if (userAgent.indexOf('Windows') > -1) {osName = 'Windows';} else if (userAgent.indexOf('Macintosh') > -1) {osName = 'macOS';}return { browserName, osName };
};
屏幕分辨率与时区
屏幕分辨率反映了用户设备屏幕的大小和显示精度,通过 screen.width
和 screen.height
获取。不同时区的用户访问网站时,服务器接收到的请求时间会有所差异,通过 Intl.DateTimeFormat().resolvedOptions().timeZone
可获取设备所在时区,这有助于分析用户的地理位置信息。
// 获取屏幕分辨率与时区
const getScreenAndTimezoneInfo = () => {const screenWidth = screen.width;const screenHeight = screen.height;const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;return { screenWidth, screenHeight, timezone };
};
二、高级指纹生成:打造设备指纹的 “独特标识”
Canvas 指纹
Canvas 是 HTML5 提供的一个绘图区域,不同设备在渲染 Canvas 图形时会因显卡驱动、抗锯齿算法等因素产生细微差异。我们可以在 Canvas 上绘制一些图形,然后将绘制结果转化为一个哈希值,这个哈希值即为 Canvas 指纹。为了增加抗伪造能力,可以在绘制过程中加入一些随机因素,如随机像素偏移。
// 获取 Canvas 指纹
const getCanvasFingerprint = () => {const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');// 设置 Canvas 尺寸canvas.width = 300;canvas.height = 200;// 绘制随机图形(包括随机像素偏移)ctx.fillStyle = '#FF0000';ctx.fillRect(10 + Math.random() * 5, 10 + Math.random() * 5, 50, 50);ctx.font = '16px Arial';ctx.fillStyle = '#0000FF';ctx.fillText('Hello, Fingerprint!', 70 + Math.random() * 3, 70 + Math.random() * 3);// 获取 Canvas 内容的 Base64 编码字符串const data = canvas.toDataURL();return data;
};
WebGL 指纹
WebGL 是一种基于浏览器的 3D 绘图技术,它可以访问设备的显卡信息。通过 WebGL,我们可以获取显卡的渲染器名称、厂商等信息,这些信息在不同设备上具有较高的唯一性。同时,还可以利用 WebGL 的计算特性,执行一些简单的计算任务,进一步增加指纹的复杂度。
// 获取 WebGL 指纹
const getWebGLFingerprint = () => {const canvas = document.createElement('canvas');const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');if (!gl) {return { renderer: 'No WebGL support', vendor: 'No WebGL support' };}const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);// 执行简单的 WebGL 计算任务,获取计算特性const computeResult = performWebGLComputation(gl);return { renderer, vendor, computeResult };function performWebGLComputation(gl) {// 创建一个简单的着色器程序const vertexShaderSource = `attribute vec4 aVertexPosition;void main() {gl_Position = aVertexPosition;}`;const fragmentShaderSource = `precision mediump float;void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}`;const vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, vertexShaderSource);gl.compileShader(vertexShader);const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, fragmentShaderSource);gl.compileShader(fragmentShader);const shaderProgram = gl.createProgram();gl.attachShader(shaderProgram, vertexShader);gl.attachShader(shaderProgram, fragmentShader);gl.linkProgram(shaderProgram);// 执行绘图操作,获取计算结果(此处仅为示例,实际计算可更复杂)const positionBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);const positions = new Float32Array([0.0, 0.0, 0.0, 0.5, 0.5, 0.0]);gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);const vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'aVertexPosition');gl.enableVertexAttribArray(vertexPositionAttribute);gl.vertexAttribPointer(vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);gl.useProgram(shaderProgram);gl.drawArrays(gl.TRIANGLES, 0, 3);// 获取绘图结果的哈希值作为计算特性的一部分const pixels = new Uint8Array(4 * 1 * 1);gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);return pixels[0].toString() + pixels[1].toString() + pixels[2].toString() + pixels[3].toString();}
};
三、行为特征融合:捕捉设备的 “动态特征”
除了设备的硬件和软件信息外,用户在使用设备时的行为特征也能为设备指纹提供重要补充。通过监听 mousemove、keydown 等事件,我们可以捕捉到用户与设备交互的模式,这些模式对于区分人机操作具有重要意义。
鼠标移动(mousemove)事件
用户在页面上移动鼠标时,会产生一连串的 mousemove 事件。我们可以记录鼠标的位置变化、移动速度以及停留时间等信息。正常用户的鼠标移动通常是比较自然和不规则的,而爬虫模拟的鼠标移动可能呈现出固定的模式或异常的速度。
// 监听 mousemove 事件并记录鼠标行为特征
let mouseMoveData = {path: [], // 鼠标移动轨迹speed: [] // 鼠标移动速度
};
document.addEventListener('mousemove', (event) => {const x = event.clientX;const y = event.clientY;const timestamp = Date.now();// 记录鼠标位置mouseMoveData.path.push({ x, y, timestamp });// 计算鼠标移动速度if (mouseMoveData.path.length > 1) {const prevPosition = mouseMoveData.path[mouseMoveData.path.length - 2];const deltaX = x - prevPosition.x;const deltaY = y - prevPosition.y;const deltaTime = timestamp - prevPosition.timestamp;const speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY) / (deltaTime / 1000); // 速度单位:像素/秒mouseMoveData.speed.push(speed);}// 限制数据长度,避免内存占用过多if (mouseMoveData.path.length > 100) {mouseMoveData.path.shift();}if (mouseMoveData.speed.length > 50) {mouseMoveData.speed.shift();}
});
键盘按下(keydown)和释放(keyup)事件
用户在输入文本时,按键的顺序、每个键的按压时长以及按键间隔等特征都能反映其操作习惯。我们可以通过监听 keydown 和 keyup 事件来记录这些信息。例如,不同用户在输入相同的密码时,按键节奏可能截然不同,这为区分正常用户和爬虫提供了有力依据。
// 监听 keydown 和 keyup 事件并记录键盘行为特征
let keyboardData = {keySequence: [], // 按键序列keyPressDurations: [] // 按键按压时长
};
document.addEventListener('keydown', (event) => {const key = event.key;const timestamp = Date.now();// 记录按键按下时间keyboardData.keySequence.push({ key, timestamp, releaseTime: null });
});
document.addEventListener('keyup', (event) => {const key = event.key;const timestamp = Date.now();// 查找对应的按键按下记录for (let i = keyboardData.keySequence.length - 1; i >= 0; i--) {if (keyboardData.keySequence[i].key === key && keyboardData.keySequence[i].releaseTime === null) {keyboardData.keySequence[i].releaseTime = timestamp;// 计算按键按压时长const pressDuration = timestamp - keyboardData.keySequence[i].timestamp;keyboardData.keyPressDurations.push(pressDuration);break;}}// 限制数据长度if (keyboardData.keySequence.length > 100) {keyboardData.keySequence.shift();}if (keyboardData.keyPressDurations.length > 50) {keyboardData.keyPressDurations.shift();}
});
四、设备指纹的应用场景
跨平台账号管理
在跨境电商平台中,设备指纹技术可以防止恶意用户通过创建虚假账号来进行欺诈活动。平台可以结合设备指纹、IP 地理信息和用户时区等多维度数据,对注册和登录的账号进行风险评估。如果发现一个账号在短时间内从不同设备指纹的设备登录,或者设备指纹与 IP 地理信息、时区不匹配,平台可以采取额外的验证措施,如发送验证码到绑定的手机号码,确保账号的安全性。
金融风控
银行系统在用户登录、转账等关键操作时,利用设备指纹技术可以有效识别异常设备登录。例如,如果一个用户的账号突然从一个从未使用过的设备登录,且该设备的指纹特征与之前常用的设备差异较大,系统可以暂时冻结该账号或要求用户进行身份验证。同时,结合用户的行为特征,如输入密码的键盘敲击模式、鼠标操作习惯等,可以进一步判断是否为用户本人操作,防范账号盗用和欺诈交易风险。
在线游戏反外挂
在线游戏行业一直受到外挂程序的困扰,这些外挂程序通常会模拟正常玩家的操作来获取不公平的优势。通过设备指纹识别技术,游戏平台可以对玩家的设备进行唯一标识,监测玩家的游戏行为是否与设备指纹对应的正常玩家行为模式相符。如果发现某个设备指纹的玩家频繁出现异常的游戏行为,如超高速移动、精准射击(不符合正常人类反应时间)等,平台可以对该账号进行封禁或限制,维护游戏的公平性和平衡性。
五、设备指纹技术的优势与挑战
优势
高准确性 :设备指纹能够综合多种硬件和软件特征,生成具有高度唯一性的标识,有效地区分不同设备,减少了误判的可能性。
难以伪造 :由于设备指纹涉及大量复杂的特征,包括硬件渲染差异、行为习惯等,爬虫很难完全模拟和伪造一个真实的设备指纹,从而提高了反爬虫的效果。
动态更新 :行为特征融合使得设备指纹可以根据用户的操作实时动态更新,即使爬虫获取了某个设备的静态指纹信息,在下一次请求时,由于行为特征的变化,仍然可以被识别出来。
挑战
浏览器限制与隐私问题 :随着浏览器隐私保护措施的加强,某些设备指纹采集技术可能会受到限制。例如,一些浏览器会禁止访问精确的硬件信息或对 Canvas 渲染结果进行干扰,这可能会影响设备指纹的准确性。同时,设备指纹技术涉及到收集用户的设备信息,可能会引发用户对隐私泄露的担忧,因此在使用该技术时需要充分考虑用户隐私保护,确保数据的合法收集和使用。
性能开销 :采集和处理设备指纹信息,尤其是高级指纹生成和行为特征融合部分,可能会对设备的性能产生一定影响。在一些低性能设备上,可能会导致页面加载变慢或卡顿。因此,需要优化算法和代码,尽量减少对设备性能的影响,确保用户体验不受损害。
设备指纹识别技术作为反爬虫领域的重要手段,为我们守护互联网数据安全提供了强大的支持。然而,它并非完美无缺,在实际应用中需要不断应对各种挑战,如浏览器限制、隐私保护和性能优化等。通过合理地使用设备指纹技术,并结合其他反爬虫手段,我们可以在保护数据安全的同时,为用户提供一个安全、可靠的网络环境。
相关文章:
基于设备指纹识别的反爬虫技术:给设备办 “身份证”
传统的封禁 IP、验证码等反爬虫手段已逐渐失效,基于设备指纹识别的反爬虫技术应运而生,成为守护数据安全的新防线。它如同给每个设备办一张独一无二的 “身份证”,精准区分正常用户与爬虫工具。 一、基础参数采集:构建设备指纹的…...
SpringAI框架中的RAG知识库检索与增强生成模型详解
SpringAI框架中的RAG知识库检索与增强生成模型详解 一、RAG简介 RAG(Retrieval-Augmented Generation)可以通过检索知识库,克服大模型训练完成后参数冻结的局限性,携带知识让大模型根据知识进行回答。 二、SpringAI框架支持的R…...
【造包工具】【Xcap】精讲Xcap构造分片包(IPv4、ipv6、4G\5G等pcap均可),图解超赞超详细!!!
目录 前言 1. XCap工具概念介绍 2. Xcap环境说明 2.1 新建报文组 2.2 导入数据包 2.3 查看报文组 2.4 复制删除报文组 3. 构造分片包 3.1 造普通/外层分片步骤: 3.2 造内层分片步骤 3.2.1 建立一个新报文 3.2.2 将组装的新报文分片 3.2.3 替换原始包内层部分 3.2…...

第三节:Vben Admin 最新 v5.0 对接后端登录接口(下)
文章目录 前言一、处理请求头Authorization二、/auth/user/info 接口前端接口后端接口三、/auth/codes 接口1.前端2.后端四、测试接口前言 上一节内容,实现了登录的/auth/login 接口,但是登陆没有完成,还需要完成下面两个接口。才能完成登录。 一、处理请求头Authorizatio…...

爬虫学习————开始
🌿自动化的思想 任何领域的发展原因————“不断追求生产方式的改革,即使得付出与耗费精力越来愈少,而收获最大化”。由此,创造出方法和设备来提升效率。 如新闻的5W原则直接让思考过程规范化、流程化。或者前端框架/后端轮子的…...

Ubuntu18.04搭建samda服务器
一.什么是Samba服务器? Samba服务器是一种基于开源协议实现的网络共享服务软件,主要用于在不同操作系统(如Windows、Linux、Unix)之间实现文件和打印机共享功能。其核心目标是解决跨平台资源共享的兼容性问题,尤其是在…...
K8S扩缩容及滚动更新和回滚
目录: 1、滚动更新1、定义Deployment配置2、应用更新 2、版本回滚1. 使用kubectl rollout undo命令 3、更新暂停与恢复1、暂停更新2、更新镜像(例如,使用kubectl set image命令)3、恢复更新 4、弹性扩缩容1、扩容命令2、缩容命令3…...
一文掌握 LVGL 9 的源码目录结构
文章目录 📂 一文掌握 LVGL 9 的源码目录结构🧭 顶层目录概览📁 1. src/ — LVGL 的核心源码(🔥重点)📁 2. examples/ — API 示例📁 3. demos/ — 综合演示项目📁 4. do…...

2025-05-10-FFmepg库裁切有水印的视频
裁后 代码 import subprocess# 文件路径 input_video_path "bg_video.mp4" output_video_path "output_video_cropped.mp4"# 裁剪视频下方的水印 def crop_video(input_video_path, output_video_path, crop_height):# 获取视频的分辨率def get_video…...
Vue3 路由配置与跳转传参完整指南
目录 一、路由配置 1. 基本路由配置 2. 动态路由配置 3. 可选参数配置 二、路由跳转与传参 1. 声明式导航 (模板中) 2. 编程式导航 (JavaScript中) 三、参数接收 1. 接收动态路由参数 2. 接收查询参数 3. 监听参数变化 四、高级用法 1. 路由元信息 2. 路由守卫控…...

opencv+opencv_contrib+cuda和VS2022编译
本文介绍使用OpenCV和OpenCV_Contrib源码及Cuda进行编译的过程,编译过程中会用到OpenCV、OpenCV_Contrib、CUDA Toolkit、cuDNN、Cmake、VS2022等工具,最终编译OpenCV的Cuda版本。 一、OpenCV下载地址 OpenCV官网下载地址:https://opencv.org/releases…...
《深挖Java中的对象生命周期与垃圾回收机制》
大家好呀!👋 今天我们要聊一个Java中超级重要的话题——对象的生命周期和垃圾回收机制。 一、先来认识Java世界的"居民"——对象 👶 在Java世界里,一切皆对象。就像现实世界中的人一样,每个Java对象也有自…...
C++中extern关键字详解:不同情况下的使用方式
在 C 中,extern 关键字主要用于声明变量或函数是在其他文件中定义的,从而可以在当前文件中使用这些变量或函数。下面详细介绍 extern 修饰全局变量、函数等的用法区别以及注意事项。 修饰全局变量 详细介绍 当 extern 用于修饰全局变量时,…...
【QT】深入理解 Qt 中的对象树:机制、用途与最佳实践
深入理解 Qt 中的对象树:机制、用途与最佳实践 在使用 Qt 编程时,你是否注意到很多对象可以设置“父对象”?比如: QPushButton* btn new QPushButton(parentWidget);这不是简单的层级结构,而是 Qt 强大而优雅的 对象…...
如何利用爬虫获得1688商品详情:实战指南
在电商运营和市场分析中,获取1688商品详情数据是一项重要任务。本文将详细介绍如何利用爬虫技术获取1688商品详情,包括准备工作、爬虫实现步骤以及注意事项。 一、准备工作 (一)注册1688开放平台账号 在1688开放平台注册开发者…...

网工实验——OSPF配置
网络拓扑图 配置 1.为每个路由器配置接口(略)(详细见RIP实验) 2.配置OSPF AR1 [AR1]ospf [AR1-ospf-1]area 1 [AR1-ospf-1-area-0.0.0.1]network 172.16.1.1 0.0.0.0 #精确配置网络,也可以像下面那条命令那样配置 …...

数据库系统概论-基础理论
数据库系统概述: 1、记录:计算机中表示和存储数据的一种格式或方法。 2、数据库(DataBase, DB):数据库是长期储存在计算机内、有组织、可共享的大量数据集合。可为各种用户共享。 3、数据库管理系统(Dat…...

从零开始学习人工智能(Python高级教程)Day6-Python3 正则表达式
一、Python3 正则表达式 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。 在 Python 中,使用 re 模块来处理正则表达式。 re 模块提供了一组函数,允许你在字符串中进行模式匹配、搜索和替换操作。 r…...

Qt开发:项目视图(Item Views)的介绍和使用
文章目录 一、清单视图(List View)1.1 基本概念1.2 使用示例(文字列表)1.3 图标文字(图标模式)1.4 常用设置1.5 完整示例 二、树视图(Tree View)2.1 基本概念2.2 常用类简介2.3 快速…...
“ES7+ React/Redux/React-Native snippets“常用快捷前缀
请注意,这是一个常用的列表,不是扩展提供的所有前缀。最完整和最新的列表请参考扩展的官方文档或在 VS Code 中查看扩展的详情页面。 React (通常用于 .js, .jsx, .ts, .tsx): rfce: React Functional Component with Export Defaultrafce: React Arro…...

keepalived详细笔记
keepalived 是一种基于VRRP(虚拟路由器冗余协议)的高可用解决方案,主要是用于服务器的负载均衡和高可用性的保障,自动将服务切换到备份服务器上,确保业务的连续性。 工作原理: VRRP协议:一组路…...

xLua笔记
Generate Code干了什么 肉眼可见的,在Asset文件夹生成了XLua/Gen文件夹,里面有一些脚本。然后对加了[CSharpCallLua]的变量寻找引用,发现它被XLua/Gen/DelegatesGensBridge引用了。也可以在这里查哪些类型加了[CSharpCallLua]。 public over…...

一周学会Pandas2 Python数据处理与分析-Pandas2数据排序操作
锋哥原创的Pandas2 Python数据处理与分析 视频教程: 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili Pandas 2提供了多种灵活的数据排序方法,主要针对 DataFrame 和 Series 对象。 1. 按值排序:s…...
obj = null; 赋值null之前没有其他引用指向obj对象,那么,当obj=null时,会被垃圾回收机制立即回收吗?
不会立即回收。 具体原因是: 赋值 obj null; 后,对象变成“不可达”,符合垃圾回收条件,但垃圾回收器并不会立刻回收它。垃圾回收是CLR自动控制的非确定性过程,什么时候执行回收取决于系统内存压力、GC策略、分代情况…...

lvm详细笔记
LVM简介 逻辑卷管理器,是Linux 系统中用于管理磁盘储存的关键技术。 LVM 则打破了磁盘分区一旦确定,其大小调整往往较为复杂,且难以灵活应对业务变化这种限制,它允许用户将多个物理分区组合卷组。例如,系统中的多个物…...

250505_HTML
HTML 1. HTML5语法与基础标签1.1 HTML5特性1.1.1 空白折叠现象1.1.2 转义字符 1.2 HTML注释1.3 基础标签1.3.1 div标签1.3.2 标题标签1.3.3 段落标签1.3.4 title1.3.5 meta 1.4 html骨架1.4.1 DTD1.4.2 html标签1.4.3 head与body标签 1.5 div标签详解1.5.1 常见class类名 2. 列…...

【HarmonyOS NEXT+AI】问答05:ArkTS和仓颉编程语言怎么选?
在“HarmonyOS NEXTAI大模型打造智能助手APP(仓颉版)”课程里面,有学员提到了这样一个问题: 鸿蒙的主推开发语言不是ArkTS吗,本课程为什么使用的是仓颉编程语言? 这里就这位同学的问题,统一做下回复,以方便…...

【专家库】Kuntal Chowdhury
昆塔尔乔杜里 Kuntal Chowdhury 是 NVIDIA 的 6G 开发者关系经理和技术布道师。他致力于推动与 NVIDIA 平台和工具的开发者和早期采用者生态系统的联系,以促进 6G 研究社区的蓬勃发展。在此之前,他是 BlueFusion, Inc. 的创始人,这是一家创新…...

【代码优化篇】强缓存和协商缓存
强缓存和协商缓存 一、强缓存与协商缓存的区别二、Vue2 前端实现强缓存(静态资源)三、Spring Boot 后端实现协商缓存(动态接口)四、测试缓存效果五、注意事项 一、强缓存与协商缓存的区别 强缓存:浏览器直接读取本地缓…...

电路中的DGND、GROUND、GROUND_REF的区别,VREF、VCC、VDD、VEE和VSS的区别?
目录 1 DGND、GROUND、GROUND_REF的区别 1.1 DGND(Digital Ground) 1.2 GROUND(Ground) 1.3 GROUND_REF(Ground Reference) 1.4 区别 2 VREF、VCC、VDD、VEE和VSS的区别 2.1 VREF(Refere…...