✨ 添加登录验证码功能 - 增强系统安全性
## 新增功能 - 密码输错2次后自动显示验证码 - 4位数字验证码,点击可刷新 - 验证码有效期5分钟 - 基于IP和用户名双重防护 - 前台和后台登录均支持 ## 后端改动 - 新增验证码生成API: GET /api/captcha - 修改登录API支持验证码验证 - 添加session管理验证码 - 增强RateLimiter防爆破机制 ## 前端改动 - 登录表单添加验证码输入框(条件显示) - 验证码图片展示和刷新功能 - 自动触发验证码显示逻辑 ## 依赖更新 - 新增: svg-captcha (验证码生成) - 新增: express-session (session管理) ## 文档 - CAPTCHA_FEATURE.md - 详细功能文档 - CAPTCHA_README.md - 快速开始指南 - test_captcha.sh - 自动化测试脚本 - 更新说明_验证码功能.txt - 中文说明 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
280
CAPTCHA_FEATURE.md
Normal file
280
CAPTCHA_FEATURE.md
Normal file
@@ -0,0 +1,280 @@
|
||||
# 登录验证码功能说明
|
||||
|
||||
## 功能概述
|
||||
|
||||
本次更新为"玩玩云"云存储系统添加了登录验证码功能,提高了系统的安全性。该功能会在用户输错密码一定次数后自动显示验证码,要求用户输入验证码才能继续尝试登录。
|
||||
|
||||
## 功能特性
|
||||
|
||||
### 1. 智能验证码触发
|
||||
- **自动触发**:当用户输错密码2次后,系统会自动显示验证码输入框
|
||||
- **适用范围**:前台用户登录和后台管理员登录均适用
|
||||
- **双重保护**:基于IP地址和用户名两个维度进行失败次数统计
|
||||
|
||||
### 2. 验证码特点
|
||||
- **纯数字验证码**:4位数字,易于识别和输入
|
||||
- **彩色显示**:验证码图片使用彩色显示,提高可读性
|
||||
- **点击刷新**:点击验证码图片即可刷新获取新的验证码
|
||||
- **有效期限**:验证码有效期为5分钟,过期后需要刷新
|
||||
- **安全存储**:验证码存储在服务器端session中,防止客户端篡改
|
||||
|
||||
### 3. 防爆破机制
|
||||
- **失败限制**:15分钟内失败5次将被封锁30分钟
|
||||
- **渐进式保护**:
|
||||
- 第1-2次失败:仅提示密码错误
|
||||
- 第3-5次失败:显示验证码要求输入
|
||||
- 第5次失败:封锁IP和用户名30分钟
|
||||
|
||||
## 技术实现
|
||||
|
||||
### 后端改动
|
||||
|
||||
#### 1. 新增依赖
|
||||
- `svg-captcha`: 用于生成SVG格式的验证码图片
|
||||
- `express-session`: 用于管理session存储验证码
|
||||
|
||||
#### 2. 新增API端点
|
||||
```
|
||||
GET /api/captcha
|
||||
```
|
||||
- 功能:生成并返回SVG格式的验证码图片
|
||||
- 返回:SVG图片数据
|
||||
- Session存储:验证码文本和生成时间
|
||||
|
||||
#### 3. 修改登录API
|
||||
```
|
||||
POST /api/login
|
||||
```
|
||||
新增参数:
|
||||
- `captcha` (可选): 验证码输入值
|
||||
|
||||
验证逻辑:
|
||||
1. 检查IP和用户名的失败次数
|
||||
2. 如果失败次数 >= 2,则要求提供验证码
|
||||
3. 验证验证码的有效性(是否存在、是否过期、是否正确)
|
||||
4. 验证码错误返回 `needCaptcha: true`
|
||||
|
||||
#### 4. RateLimiter增强
|
||||
- 新增 `getFailureCount()` 方法:获取指定key的失败次数
|
||||
- `recordFailure()` 返回值新增 `needCaptcha` 字段
|
||||
|
||||
### 前端改动
|
||||
|
||||
#### 1. 数据字段
|
||||
新增:
|
||||
```javascript
|
||||
showCaptcha: false, // 是否显示验证码
|
||||
captchaUrl: '', // 验证码图片URL
|
||||
loginForm.captcha: '' // 验证码输入值
|
||||
```
|
||||
|
||||
#### 2. UI组件
|
||||
在登录表单中添加:
|
||||
- 验证码输入框(条件显示)
|
||||
- 验证码图片显示区域
|
||||
- 点击刷新提示文字
|
||||
|
||||
#### 3. 逻辑方法
|
||||
新增 `refreshCaptcha()` 方法:
|
||||
```javascript
|
||||
refreshCaptcha() {
|
||||
this.captchaUrl = `${this.apiBase}/api/captcha?t=${Date.now()}`;
|
||||
}
|
||||
```
|
||||
|
||||
修改 `handleLogin()` 方法:
|
||||
- 登录失败时检查 `response.data.needCaptcha`
|
||||
- 如果需要验证码,显示验证码并调用 `refreshCaptcha()`
|
||||
- 登录成功后隐藏验证码并清空输入
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 用户使用流程
|
||||
|
||||
1. **首次登录尝试**
|
||||
- 输入用户名和密码
|
||||
- 点击"登录"按钮
|
||||
- 如果密码错误,会提示"用户名或密码错误"
|
||||
|
||||
2. **第三次登录尝试(触发验证码)**
|
||||
- 输入用户名和密码
|
||||
- 系统自动显示验证码输入框
|
||||
- 输入图片中显示的4位数字
|
||||
- 如果看不清,点击图片刷新验证码
|
||||
- 点击"登录"按钮
|
||||
|
||||
3. **验证码验证**
|
||||
- 如果验证码错误,会提示"验证码错误",验证码会自动刷新
|
||||
- 如果验证码过期,会提示"验证码已过期,请刷新验证码"
|
||||
- 验证码正确且密码正确,登录成功
|
||||
|
||||
4. **账号封锁**
|
||||
- 如果连续失败5次,账号将被封锁30分钟
|
||||
- 封锁期间尝试登录会提示"账号已被封禁"
|
||||
|
||||
### 管理员说明
|
||||
|
||||
管理员登录时同样受到验证码保护,流程与普通用户完全一致。
|
||||
|
||||
## 配置说明
|
||||
|
||||
### Session配置
|
||||
|
||||
在 `backend/server.js` 中配置session:
|
||||
|
||||
```javascript
|
||||
app.use(session({
|
||||
secret: process.env.SESSION_SECRET || 'your-session-secret-change-in-production',
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
cookie: {
|
||||
secure: process.env.COOKIE_SECURE === 'true',
|
||||
httpOnly: true,
|
||||
maxAge: 10 * 60 * 1000 // 10分钟
|
||||
}
|
||||
}));
|
||||
```
|
||||
|
||||
建议在 `.env` 文件中设置:
|
||||
```
|
||||
SESSION_SECRET=你的session密钥
|
||||
```
|
||||
|
||||
### 验证码参数
|
||||
|
||||
在 `backend/server.js` 的验证码生成代码中可调整:
|
||||
|
||||
```javascript
|
||||
const captcha = svgCaptcha.create({
|
||||
size: 4, // 验证码长度(4位数字)
|
||||
noise: 2, // 干扰线条数
|
||||
color: true, // 使用彩色
|
||||
background: '#f0f0f0', // 背景色
|
||||
width: 120, // 宽度
|
||||
height: 40, // 高度
|
||||
fontSize: 50, // 字体大小
|
||||
charPreset: '0123456789' // 只使用数字
|
||||
});
|
||||
```
|
||||
|
||||
### 防爆破参数
|
||||
|
||||
在 `backend/server.js` 中配置RateLimiter:
|
||||
|
||||
```javascript
|
||||
const loginLimiter = new RateLimiter({
|
||||
maxAttempts: 5, // 最大失败次数
|
||||
windowMs: 15 * 60 * 1000, // 统计窗口(15分钟)
|
||||
blockDuration: 30 * 60 * 1000 // 封锁时长(30分钟)
|
||||
});
|
||||
```
|
||||
|
||||
**验证码触发阈值**在登录逻辑中设置:
|
||||
```javascript
|
||||
const needCaptcha = ipFailures >= 2 || usernameFailures >= 2;
|
||||
```
|
||||
可以修改 `>= 2` 来调整触发次数。
|
||||
|
||||
## 安全建议
|
||||
|
||||
1. **设置SESSION_SECRET**
|
||||
- 在生产环境中务必设置强随机的SESSION_SECRET
|
||||
- 使用 `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"` 生成
|
||||
|
||||
2. **启用HTTPS**
|
||||
- 在生产环境中设置 `COOKIE_SECURE=true`
|
||||
- 确保使用HTTPS协议
|
||||
|
||||
3. **定期审计**
|
||||
- 定期检查登录失败日志
|
||||
- 关注异常的登录尝试
|
||||
|
||||
4. **调整参数**
|
||||
- 根据实际使用情况调整失败次数阈值
|
||||
- 根据用户反馈调整验证码难度
|
||||
|
||||
## 测试方法
|
||||
|
||||
### 测试验证码显示
|
||||
|
||||
1. 启动服务器:`cd backend && node server.js`
|
||||
2. 访问登录页面
|
||||
3. 使用错误的用户名或密码登录2次
|
||||
4. 第3次尝试时应该看到验证码输入框
|
||||
|
||||
### 测试验证码API
|
||||
|
||||
```bash
|
||||
curl "http://localhost:40001/api/captcha" > test.svg
|
||||
```
|
||||
|
||||
查看生成的 test.svg 文件,应该显示一个4位数字的验证码。
|
||||
|
||||
### 测试登录流程
|
||||
|
||||
```bash
|
||||
# 第一次失败(无验证码)
|
||||
curl -X POST http://localhost:40001/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"test","password":"wrong"}'
|
||||
|
||||
# 第二次失败(无验证码)
|
||||
curl -X POST http://localhost:40001/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"test","password":"wrong"}'
|
||||
|
||||
# 第三次失败(需要验证码)
|
||||
curl -X POST http://localhost:40001/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"test","password":"wrong"}'
|
||||
# 返回: {"success":false,"message":"请输入验证码","needCaptcha":true}
|
||||
```
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 问题1:验证码不显示
|
||||
|
||||
**可能原因**:
|
||||
- Session未正确配置
|
||||
- 前端未正确接收 `needCaptcha` 标志
|
||||
|
||||
**解决方法**:
|
||||
- 检查浏览器控制台是否有错误
|
||||
- 检查后端日志是否有session相关错误
|
||||
- 确认 `express-session` 依赖已安装
|
||||
|
||||
### 问题2:验证码一直提示错误
|
||||
|
||||
**可能原因**:
|
||||
- Session未持久化
|
||||
- 验证码大小写不匹配
|
||||
|
||||
**解决方法**:
|
||||
- 验证码已统一转换为小写进行比较
|
||||
- 检查浏览器是否禁用了Cookie
|
||||
|
||||
### 问题3:验证码图片不加载
|
||||
|
||||
**可能原因**:
|
||||
- CORS配置问题
|
||||
- API路径错误
|
||||
|
||||
**解决方法**:
|
||||
- 检查 `ALLOWED_ORIGINS` 环境变量配置
|
||||
- 确认API基础路径配置正确
|
||||
|
||||
## 更新日志
|
||||
|
||||
**版本:1.1.0**
|
||||
- 新增登录验证码功能
|
||||
- 密码错误2次后自动显示验证码
|
||||
- 支持点击刷新验证码
|
||||
- 验证码有效期5分钟
|
||||
- 前台和后台登录均支持
|
||||
|
||||
## 技术支持
|
||||
|
||||
如有问题,请查看:
|
||||
- 项目README.md
|
||||
- GitHub Issues
|
||||
- 后端日志文件
|
||||
Reference in New Issue
Block a user