# 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 实现的滑动验证码系统,支持随机生成验证码图案,具备强大的行为数据验证能力。

## 功能特性
- ✅ 随机生成验证码图案(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