# nodejs-滑动验证码 **Repository Path**: yanfanVIP/nodejs---sliding-captcha ## Basic Information - **Project Name**: nodejs-滑动验证码 - **Description**: 后端基于Nodejs的滑动验证码 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-08 - **Last Updated**: 2026-01-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 滑动验证码系统 一个基于 Node.js 和原生 JavaScript 实现的滑动验证码系统,支持随机生成验证码图案,具备强大的行为数据验证能力。 ![输入图片说明](public/image.png) ## 功能特性 - ✅ 随机生成验证码图案(SVG 背景图和拼图块) - ✅ 前端拖拽交互,支持鼠标和触摸操作 - ✅ 后端位置验证(5像素容差) - ✅ **强化的用户行为数据验证**(10+ 种防 AI 检测机制) - 速度和加速度曲线分析 - 轨迹平滑度检测 - 人类行为特征识别 - 时间间隔规律性检测 - ✅ 验证码会话管理(5分钟过期) - ✅ 美观的现代化 UI 界面 - ✅ 多语言支持(中文、英文、日文、韩文) - ✅ 客户端库封装,易于集成 ## 技术栈 - **后端**: Node.js + Express - **前端**: 原生 JavaScript + HTML + CSS - **图片生成**: `node-puzzle` + `sharp` (用于生成拼图和随机背景) - **核心库**: `lib/captcha.js` - 可独立使用的验证码库 - **客户端库**: `public/client.js` - 封装的客户端库,支持 JS 调用 ## 快速开始 ### 1. 安装依赖 ```bash npm install ``` **注意**: 本项目使用 SVG 生成验证码图片,无需安装 canvas 等需要系统依赖的库,安装过程更简单快速。 ### 2. 启动服务器 ```bash npm start ``` 服务器将在 `http://localhost:3000` 启动。 ### 3. 访问应用 在浏览器中打开 `http://localhost:3000` 即可体验滑动验证码功能。 ### 4. 测试 API 使用浏览器或 Postman 测试: - **生成验证码**: GET `http://localhost:3000/api/captcha/generate` - **验证位置**: POST `http://localhost:3000/api/captcha/verify` ## 项目结构 ``` slide-captcha/ ├── server.js # Express API 服务器(调用库) ├── lib/ # 核心库目录 │ ├── captcha.js # 验证码核心库(可独立使用) │ └── example.js # 库使用示例 ├── package.json # 项目依赖配置 ├── public/ # 前端静态文件 │ ├── index.html # 主页面(原始版本) │ ├── example.html # 使用 client.js 的示例页面 │ ├── style.css # 样式文件(原始版本) │ ├── captcha.js # 验证码交互逻辑(原始版本) │ └── client.js # 封装的客户端库(推荐使用) ├── documents/ # 项目文档 └── README.md # 项目说明 ``` ## API 接口 ### 生成验证码 **GET** `/api/captcha/generate` **响应示例**: ```json { "success": true, "sessionId": "uuid-string", "background": "data:image/png;base64,...", "puzzle": "data:image/png;base64,..." } ``` ### 验证滑动位置 **POST** `/api/captcha/verify` **请求体**: ```json { "sessionId": "uuid-string", "slideX": 150 } ``` **响应示例**: ```json { "success": true, "message": "验证成功" } ``` ## 工作原理 1. **生成阶段**: 核心库(`lib/captcha.js`)使用 SVG 随机生成一个带缺口的背景图和对应的拼图块 2. **展示阶段**: 前端显示背景图,拼图块初始位置在左侧 3. **交互阶段**: 用户拖动滑块,拼图块同步移动 4. **验证阶段**: 用户释放滑块后,前端发送滑动位置到服务器,服务器调用库进行验证 5. **结果**: 库检查滑动位置是否与生成的缺口位置匹配(允许5像素误差) ## 前端集成教程 ### 方式一:直接使用(最简单) 1. **启动服务器** ```bash npm start ``` 2. **访问页面** - 打开浏览器访问:`http://localhost:3000` - 直接体验完整的验证码功能 ### 方式二:集成到现有项目(推荐) #### 步骤 1: 复制前端文件 将以下文件复制到你的项目: ``` public/index.html → 参考验证码 HTML 结构 public/style.css → 验证码样式 public/captcha.js → 验证码交互逻辑(或使用 client.js) ``` #### 步骤 2: 在你的 HTML 中引入 ```html 我的网站
加载中...
请拖动滑块完成验证
``` #### 步骤 3: 配置 API 地址 修改 `captcha.js` 中的 API 地址(如果你的后端不在同一域名): ```javascript // 在 captcha.js 的 loadCaptcha 方法中 async loadCaptcha() { const response = await fetch('http://your-api-domain.com/api/captcha/generate'); // ... } async verify() { const response = await fetch('http://your-api-domain.com/api/captcha/verify', { // ... }); } ``` ### 方式三:使用封装的客户端库(最灵活) 使用 `public/client.js` 客户端库,自动注入 HTML 和 CSS: ```html 滑动验证码
``` **配置选项**: | 选项 | 类型 | 必需 | 默认值 | 说明 | |------|------|------|--------|------| | `container` | Element | ✅ | - | 验证码容器元素 | | `apiBaseUrl` | String | - | `/api/captcha` | API 基础路径 | | `width` | Number | - | 300 | 验证码宽度 | | `height` | Number | - | 150 | 验证码高度 | | `onSuccess` | Function | - | - | 验证成功回调 | | `onError` | Function | - | - | 验证失败回调 | | `onVerify` | Function | - | - | 验证结果回调 | **API 方法**: - `init()`: 初始化验证码 - `refresh()`: 刷新验证码 - `destroy()`: 销毁验证码实例 - `reset()`: 重置验证码状态 ## 后端集成教程 ### 方式一:使用现成的 Express 服务器 直接使用项目提供的 `app.js`: ```bash # 启动服务器 node app.js # 服务器运行在 http://localhost:3000 ``` ### 方式二:集成到现有 Express 项目 #### 步骤 1: 复制核心库 将 `captcha.js` 复制到你的项目: ```bash cp captcha.js your-project/lib/captcha.js ``` #### 步骤 2: 安装依赖 ```bash npm install uuid sharp node-puzzle ``` #### 步骤 3: 创建验证码实例和路由 ```javascript const express = require('express'); const SlideCaptcha = require('./lib/captcha'); const app = express(); app.use(express.json()); // 创建会话存储(生产环境建议使用 Redis) const sessions = new Map(); // 创建验证码实例 const captcha = new SlideCaptcha(sessions, { width: 300, height: 150, puzzleSize: 50, tolerance: 5, expireTime: 5 * 60 * 1000, language: 'zh-CN' // 支持: zh-CN, en-US, ja-JP, ko-KR }); // 生成验证码接口 app.get('/api/captcha/generate', async (req, res) => { try { const result = await captcha.generate(); res.json({ success: true, ...result }); } catch (error) { console.error('生成验证码失败:', error); res.status(500).json({ success: false, message: '生成验证码失败' }); } }); // 验证接口 app.post('/api/captcha/verify', (req, res) => { const { sessionId, slideX, behaviorData } = req.body; const result = captcha.verify(sessionId, slideX, behaviorData, { validateBehavior: true, // 启用行为验证 recordAttempt: true, keepSessionOnFailure: false }); res.json(result); }); app.listen(3000, () => { console.log('服务器运行在 http://localhost:3000'); }); ``` ### 方式三:直接使用核心库(不使用 Express) ```javascript const SlideCaptcha = require('./captcha'); // 创建会话存储 const sessions = new Map(); // 创建实例 const captcha = new SlideCaptcha(sessions, { width: 300, height: 150, puzzleSize: 50, tolerance: 5, expireTime: 5 * 60 * 1000 }); // 生成验证码 async function generateCaptcha() { const result = await captcha.generate(); console.log('验证码生成成功'); console.log('SessionID:', result.sessionId); console.log('背景图:', result.background.substring(0, 50) + '...'); console.log('拼图块:', result.puzzle.substring(0, 50) + '...'); return result; } // 验证滑动位置 function verifyCaptcha(sessionId, slideX, behaviorData) { const result = captcha.verify(sessionId, slideX, behaviorData, { validateBehavior: true, tolerance: 5 }); if (result.success) { console.log('✅ 验证成功!'); } else { console.log('❌ 验证失败:', result.message); } return result; } // 使用示例 (async () => { const captchaData = await generateCaptcha(); // 模拟用户滑动 const mockBehaviorData = { tracks: [ { x: 0, time: 0 }, { x: 50, time: 100 }, { x: 100, time: 200 }, { x: 150, time: 300 } ], startTime: Date.now(), endTime: Date.now() + 300, totalTime: 300 }; // 验证(假设正确位置是 150) verifyCaptcha(captchaData.sessionId, 150, mockBehaviorData); })(); ``` ### 核心库配置选项 ```javascript const captcha = new SlideCaptcha(sessions, { width: 300, // 验证码宽度(像素) height: 150, // 验证码高度(像素) puzzleSize: 50, // 拼图块大小(像素) tolerance: 5, // 验证容差(像素) expireTime: 300000, // 会话过期时间(毫秒,默认 5 分钟) language: 'zh-CN' // 语言:zh-CN, en-US, ja-JP, ko-KR }); ``` ### API 方法说明 #### `generate()` - 生成验证码 ```javascript const result = await captcha.generate(); // 返回: // { // sessionId: 'uuid-string', // background: 'data:image/png;base64,...', // puzzle: 'data:image/png;base64,...', // puzzleSize: 50, // bg_width: 300, // bg_height: 150 // } ``` #### `verify(sessionId, slideX, behaviorData, options)` - 验证 ```javascript const result = captcha.verify( 'session-id', 150, // 滑动的 X 坐标 behaviorData, // 用户行为数据(可选) { validateBehavior: true, // 是否启用行为验证 recordAttempt: true, // 是否记录尝试次数 keepSessionOnFailure: false, // 失败后是否保留会话 tolerance: 5 // 自定义容差 } ); // 返回: // { // success: true/false, // message: '验证成功', // code: 'SUCCESS', // distanceX: 2.5, // distanceY: 0, // totalDistance: 2.5 // } ``` #### `getSession(sessionId)` - 获取会话信息 ```javascript const session = captcha.getSession('session-id'); // 返回: // { // puzzleX: 150, // puzzleY: 50, // puzzleSize: 50, // timestamp: 1234567890, // expiresAt: 1234567890, // attempts: 0 // } ``` ### 运行示例 查看完整的使用示例: ```bash # 查看示例代码 cat lib/example.js # 运行示例 node lib/example.js ``` ## 行为数据验证详解 本系统实现了**10+ 种防 AI 检测机制**,确保验证码的安全性: ### 验证维度 1. **速度分析** - 平均速度范围检测(0.05 - 3 像素/毫秒) - 最大速度限制(≤10 像素/毫秒) - 速度方差检测(防止速度过于均匀) 2. **加速度曲线检测** - 加速度异常检测(防止瞬间加速) - 加速度方差检测(确保自然的加减速) 3. **轨迹平滑度** - 方向变化检测(防止完美直线) - 轨迹抖动检测(防止过度抖动) 4. **时间特征** - 总时间范围(300ms - 10s) - 时间间隔规律性检测 - 起始/结束速度检测 5. **路径分析** - 路径效率检测(0.5 - 0.99) - 停顿检测(人类特征) - 位移合理性检测 ### 行为数据格式 ```javascript const behaviorData = { tracks: [ // 轨迹点数组 { x: 0, time: 0 }, { x: 10, time: 50 }, { x: 25, time: 120 }, // ... ], startTime: 1609459200000, // 开始时间戳 endTime: 1609459201000, // 结束时间戳 totalTime: 1000 // 总时长(毫秒) }; ``` ## 配置说明 ### 默认配置 ```javascript { width: 300, // 验证码宽度 height: 150, // 验证码高度 puzzleSize: 50, // 拼图块大小 tolerance: 5, // 验证容差(像素) expireTime: 300000, // 5分钟过期 language: 'zh-CN' // 默认语言 } ``` ### 自定义配置示例 ```javascript const captcha = new SlideCaptcha(sessions, { width: 400, // 更大的验证码 height: 200, puzzleSize: 60, tolerance: 8, // 更宽松的容差 expireTime: 600000, // 10分钟过期 language: 'en-US' // 英文界面 }); ``` ## 生产环境部署 ### 1. 使用 Redis 存储会话 ```javascript const Redis = require('ioredis'); const redis = new Redis(); // 自定义会话存储 class RedisSessionStore { async set(key, value) { await redis.setex(key, 300, JSON.stringify(value)); } async get(key) { const data = await redis.get(key); return data ? JSON.parse(data) : null; } async delete(key) { await redis.del(key); } } const sessionStore = new RedisSessionStore(); const captcha = new SlideCaptcha(sessionStore, options); ``` ### 2. 添加频率限制 ```javascript const rateLimit = require('express-rate-limit'); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 分钟 max: 100 // 限制 100 次请求 }); app.use('/api/captcha', limiter); ``` ### 3. 添加 IP 验证 ```javascript app.post('/api/captcha/verify', (req, res) => { const ip = req.ip || req.connection.remoteAddress; // 检查 IP 黑名单 if (isBlacklisted(ip)) { return res.status(403).json({ success: false, message: 'IP 已被封禁' }); } // 继续验证... }); ``` ### 4. 使用 HTTPS ```javascript const https = require('https'); const fs = require('fs'); const options = { key: fs.readFileSync('private-key.pem'), cert: fs.readFileSync('certificate.pem') }; https.createServer(options, app).listen(443); ``` ## 性能优化 - **图片缓存**: SVG 生成较快,但大量并发时建议缓存 - **CDN 加速**: 静态资源使用 CDN 分发 - **负载均衡**: 使用 Nginx 进行负载均衡 - **会话清理**: 定期清理过期会话 ## 常见问题 ### Q: 验证总是失败? A: 检查前端发送的 `slideX` 是否正确,容差默认为 5 像素。 ### Q: 如何调整验证难度? A: 修改 `tolerance` 参数,值越小难度越大。 ### Q: 如何禁用行为验证? A: 在 `verify` 方法中设置 `validateBehavior: false`。 ### Q: 支持移动端吗? A: 完全支持,包含触摸事件处理。 ### Q: 如何自定义样式? A: 修改 `public/style.css` 中的样式。 ## 注意事项 - ⚠️ **会话存储**: 生产环境必须使用 Redis 等持久化存储 - ⚠️ **HTTPS**: 生产环境必须使用 HTTPS 保护数据传输 - ⚠️ **频率限制**: 建议添加 IP 频率限制防止暴力破解 - ⚠️ **日志记录**: 记录验证失败的 IP 和会话,用于安全分析 - ✅ **无系统依赖**: 使用 SVG 生成,无需安装 canvas 系统库 - ✅ **独立使用**: 核心库可在任何 Node.js 项目中使用 ## 许可证 MIT