Files
vue-driven-cloud-storage/交接文档_验证码功能.md

686 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 玩玩云 - 验证码功能交接文档
> 创建时间2025年11月21日
> 项目名称vue-driven-cloud-storage玩玩云存储系统
> 功能:登录验证码功能实现与部署
---
## 📦 项目信息
### Gitee仓库
- **仓库地址**: https://gitee.com/yu-yon/vue-driven-cloud-storage.git
- **用户名**: `yu-yon`
- **私人令牌**: `54434786369b55e02e98f5ed6825a2e6`
### Git配置
```bash
git config user.name '喻勇祥'
git config user.email '237899745@qq.com'
```
### 克隆命令
```bash
git clone https://gitee.com/yu-yon/vue-driven-cloud-storage.git
```
### 使用令牌推送
```bash
git push https://yu-yon:54434786369b55e02e98f5ed6825a2e6@gitee.com/yu-yon/vue-driven-cloud-storage.git master
```
---
## ✨ 本次功能更新概述
### 功能说明
添加登录验证码功能,提高系统安全性:
- 密码输错2次后自动显示验证码
- 4位纯数字验证码可点击刷新
- 验证码有效期5分钟
- 基于IP和用户名双重防护
- 前台和后台登录均支持
### 技术实现
- **后端**: Express + express-session + svg-captcha
- **前端**: Vue 3 + axios
- **部署**: Nginx反向代理 + Node.js后端
---
## 📝 本次提交记录
共提交了**7个commit**到Gitee master分支
### 1. `61c99ce` - ✨ 添加登录验证码功能
**时间**: 2025-11-21
**后端改动**:
- 安装依赖: `svg-captcha`, `express-session`
- 新增API: `GET /api/captcha` (生成验证码)
- 修改API: `POST /api/login` (支持验证码验证)
- 增强RateLimiter: 添加`getFailureCount()`方法
**前端改动**:
- 登录表单添加验证码输入框(条件显示)
- 验证码图片展示和刷新功能
- 自动触发验证码显示逻辑
**新增文档**:
- `CAPTCHA_FEATURE.md` - 详细功能文档
- `CAPTCHA_README.md` - 快速开始指南
- `test_captcha.sh` - 自动化测试脚本
- `更新说明_验证码功能.txt` - 中文说明
### 2. `7ce9d95` - 🐛 修复验证码Session问题
**问题**: Session配置导致验证码无法保存
**修复内容**:
```javascript
// backend/server.js
session({
saveUninitialized: true, // false → true
name: 'captcha.sid',
cookie: {
sameSite: 'lax' // 新增
}
})
```
### 3. `83773ef` - 🐛 修复验证码跨域Cookie传递问题
**问题**: axios不携带credentials导致cookie无法传递
**修复内容**:
```javascript
// frontend/app.js mounted()
axios.defaults.withCredentials = true;
```
### 4. `fca00aa` - 🔄 更新前端版本号
**问题**: 浏览器缓存旧版本js文件
**修复内容**:
```html
<!-- frontend/app.html -->
app.js?v=20251110001 → app.js?v=20251121001
```
### 5. `5f3fd38` - 🐛 修复Nginx Cookie传递问题 ⚠️ **最关键**
**问题**: Nginx反向代理默认不传递Cookie
**修复内容**:
```nginx
# nginx/nginx.conf - location /api 块中添加
proxy_set_header Cookie $http_cookie;
proxy_pass_header Set-Cookie;
```
### 6. `225c3a5` - 🔧 更新install.sh
**问题**: 安装脚本生成的Nginx配置缺少Cookie设置
**修复内容**:
- 修改install.sh的3处`location /api`配置
- 添加自动修复脚本: `fix_install_sh.sh`
- 添加详细说明: `INSTALL_SH_UPDATE.md`
### 7. `3ef0fa8` - 📖 添加验证码快速修复指南
**新增文档**: `CAPTCHA_QUICK_FIX.md`
---
## 🔧 完整的验证码工作原理
### 1. 验证码生成流程
```
浏览器 → GET /api/captcha
后端生成验证码图片(SVG)
后端创建session: req.session.captcha = "1234"
后端返回: Set-Cookie: captcha.sid=xxx
Nginx传递Cookie到浏览器
浏览器保存cookie
```
### 2. 验证码验证流程
```
浏览器 → POST /api/login (带Cookie: captcha.sid=xxx)
Nginx传递Cookie到后端
后端读取session: req.session.captcha
对比用户输入: captcha === session.captcha
验证成功/失败
```
### 3. 配置依赖关系
验证码功能需要**三层配置**同时生效:
```
┌─────────────────────────────────────────────┐
│ 1. 前端配置 (frontend/app.js) │
│ axios.defaults.withCredentials = true │
│ → 确保请求携带cookie │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ 2. Nginx配置 (nginx.conf) │
│ proxy_set_header Cookie $http_cookie │
│ proxy_pass_header Set-Cookie │
│ → 确保Cookie在Nginx层传递 │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ 3. 后端配置 (backend/server.js) │
│ session({ saveUninitialized: true }) │
│ → 确保session被创建和保存 │
└─────────────────────────────────────────────┘
```
**缺少任何一层都会导致验证码失败!**
---
## ⚠️ 当前存在的问题
### 生产环境验证码不工作
**症状**:
- 验证码一直提示"已过期"
- 测试发现: `curl -si https://cs.workyai.cn/api/captcha` **没有返回Set-Cookie**
**根本原因**:
生产环境的Nginx配置**没有应用Cookie传递设置**
**证据**:
```bash
curl -si https://cs.workyai.cn/api/captcha
HTTP/2 200
❌ 缺少: Set-Cookie: captcha.sid=...
```
### 需要修复的步骤
#### 方法1手动修复推荐
1. **SSH登录生产服务器**
```bash
ssh root@你的服务器IP
```
2. **找到Nginx配置文件**
```bash
# 查找配置文件
find /etc/nginx -name "*.conf" | xargs grep -l "workyai.cn"
# 或
find /www/server -name "*.conf" | xargs grep -l "40001"
# 输出示例: /etc/nginx/conf.d/玩玩云.conf
```
3. **编辑配置文件**
```bash
vim /etc/nginx/conf.d/玩玩云.conf # 替换为实际路径
```
4. **找到 location /api 块**
```nginx
location /api {
proxy_pass http://localhost:40001;
...
proxy_set_header X-Forwarded-Proto $scheme;
# ⬇️ 在这一行后面添加3行 ⬇️
# Cookie传递配置验证码session需要
proxy_set_header Cookie $http_cookie;
proxy_pass_header Set-Cookie;
# 上传超时设置
...
}
```
5. **测试并重载**
```bash
# 测试配置
nginx -t
# 重新加载
nginx -s reload
```
6. **验证修复**
```bash
# 测试验证码API应该返回Set-Cookie
curl -si http://localhost:40001/api/captcha | grep -i "set-cookie"
# 期望输出:
# Set-Cookie: captcha.sid=s%3A...; Path=/; HttpOnly; SameSite=Lax
```
#### 方法2自动修复脚本
在服务器上运行:
```bash
cd /root/vue-driven-cloud-storage # 项目路径
# 拉取最新代码
git pull origin master
# 运行自动修复脚本
sudo bash << 'AUTO_FIX'
#!/bin/bash
set -e
echo "🔧 自动修复Nginx配置..."
# 查找配置文件
CONF=$(find /etc/nginx /www/server -name "*.conf" -exec grep -l "location /api" {} \; 2>/dev/null | grep -v backup | head -1)
if [[ -z "$CONF" ]]; then
echo "❌ 未找到配置文件"
exit 1
fi
echo "找到: $CONF"
# 备份
cp "$CONF" "${CONF}.backup.$(date +%Y%m%d%H%M%S)"
# 添加Cookie配置
if ! grep -q "proxy_set_header Cookie" "$CONF"; then
sed -i '/proxy_set_header X-Forwarded-Proto \$scheme;/a\
\
# Cookie传递配置验证码session需要\
proxy_set_header Cookie $http_cookie;\
proxy_pass_header Set-Cookie;' "$CONF"
echo "✅ 已添加Cookie配置"
else
echo "✅ Cookie配置已存在"
fi
# 测试并重载
nginx -t && nginx -s reload
echo "✅ 修复完成!"
echo ""
echo "验证修复:"
curl -si http://localhost:40001/api/captcha | grep -i "set-cookie"
AUTO_FIX
```
---
## 🧪 本地测试步骤
### 环境准备
```bash
# 克隆项目
git clone https://gitee.com/yu-yon/vue-driven-cloud-storage.git
cd vue-driven-cloud-storage
# 安装后端依赖
cd backend
npm install
# 安装前端依赖(如需要)
cd ../frontend
# (前端通常无需安装,静态文件)
```
### 启动后端
```bash
cd backend
node server.js
# 或使用PM2
pm2 start server.js --name backend
# 查看日志
pm2 logs backend
```
### 启动前端使用简单HTTP服务器
```bash
cd frontend
# 方法1: Python
python3 -m http.server 3000
# 方法2: Node.js http-server
npx http-server -p 3000
# 方法3: Nginx推荐模拟生产环境
# 使用项目中的 nginx/nginx.conf
```
### 配置Nginx本地测试
```bash
# 复制配置
sudo cp nginx/nginx.conf /etc/nginx/conf.d/玩玩云-本地.conf
# 修改配置中的路径
sudo vim /etc/nginx/conf.d/玩玩云-本地.conf
# 修改 root 路径为你的实际路径
# 修改 proxy_pass 为 http://localhost:40001
# 测试并重载
sudo nginx -t
sudo nginx -s reload
```
### 测试验证码功能
1. **访问登录页面**
```
http://localhost:80
```
2. **触发验证码**
- 输入任意用户名: `test`
- 输入错误密码: `wrong`
- 点击登录2次
- 第3次尝试应该显示验证码
3. **测试验证码验证**
- 输入验证码图片中的数字
- 如果不清楚,点击图片刷新
- 验证码应该能正常验证
4. **检查浏览器**
- F12 → Network
- 查看 `/api/captcha` 请求
- Response Headers应该有: `Set-Cookie: captcha.sid=...`
- 查看 `/api/login` 请求
- Request Headers应该有: `Cookie: captcha.sid=...`
### 测试命令行
```bash
# 测试验证码生成
curl -vi http://localhost:40001/api/captcha | grep -i "set-cookie"
# 完整流程测试
# 1. 生成验证码并保存cookie
curl -s http://localhost:40001/api/captcha -c cookies.txt > /dev/null
# 2. 查看cookie
cat cookies.txt
# 3. 使用cookie登录
curl -v http://localhost:40001/api/login \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123","captcha":"1234"}'
# 清理
rm cookies.txt
```
---
## 📂 重要文件清单
### 后端文件
```
backend/
├── server.js # ✅ 已修改 - session配置、验证码API
├── package.json # ✅ 已修改 - 新增依赖
├── package-lock.json # ✅ 已修改
├── auth.js # 无修改
└── database.js # 无修改
```
### 前端文件
```
frontend/
├── app.html # ✅ 已修改 - 验证码UI、版本号
└── app.js # ✅ 已修改 - withCredentials、验证码逻辑
```
### Nginx配置
```
nginx/
└── nginx.conf # ✅ 已修改 - Cookie传递配置
```
### 部署脚本
```
install.sh # ✅ 已修改 - 3处Cookie配置
fix_install_sh.sh # ✅ 新增 - 自动修复脚本
```
### 文档
```
CAPTCHA_FEATURE.md # ✅ 新增 - 详细功能文档
CAPTCHA_README.md # ✅ 新增 - 快速开始
CAPTCHA_QUICK_FIX.md # ✅ 新增 - 快速修复指南
INSTALL_SH_UPDATE.md # ✅ 新增 - install.sh修改说明
更新说明_验证码功能.txt # ✅ 新增 - 中文说明
test_captcha.sh # ✅ 新增 - 测试脚本
交接文档_验证码功能.md # ✅ 本文档
```
---
## 🔍 问题诊断工具
### 检查Nginx配置
```bash
# 查看完整配置
nginx -T | grep -A 30 "location /api"
# 检查Cookie配置
nginx -T | grep -i "proxy_set_header cookie"
# 查找配置文件
find /etc/nginx -name "*.conf" -exec grep -l "workyai.cn" {} \;
```
### 检查后端状态
```bash
# 检查进程
ps aux | grep "node.*server"
# 检查端口
netstat -tlnp | grep 40001
# 检查依赖
cd backend && npm list | grep -E "(session|captcha)"
# 查看日志
pm2 logs backend
# 或
tail -f backend/logs/error.log
```
### 测试验证码API
```bash
# 本地测试
curl -vi http://localhost:40001/api/captcha
# 远程测试
curl -vi https://cs.workyai.cn/api/captcha
# 完整测试
bash test_captcha.sh
```
---
## 📞 联系方式
### Git配置
- 用户名: 喻勇祥
- 邮箱: 237899745@qq.com
### 项目信息
- Gitee: https://gitee.com/yu-yon
- 项目: vue-driven-cloud-storage
---
## 📅 后续工作计划
### 必须完成
1. ✅ 完成代码提交已完成7个commit
2. ⚠️ **修复生产环境Nginx配置**(待完成)
3. ⚠️ 验证生产环境验证码功能(待完成)
### 建议完成
1. 添加验证码样式优化
2. 添加验证码错误次数限制
3. 添加登录日志记录
4. 考虑添加滑动验证码
### 优化建议
1. 设置生产环境的SESSION_SECRET
2. 启用HTTPS时设置COOKIE_SECURE=true
3. 配置ALLOWED_ORIGINS白名单
4. 定期清理失败的登录尝试记录
---
## 📋 验证清单
部署完成后,使用此清单验证:
### 后端检查
- [ ] express-session依赖已安装
- [ ] svg-captcha依赖已安装
- [ ] server.js包含session配置
- [ ] server.js包含验证码API
- [ ] server.js包含验证码验证逻辑
- [ ] 后端服务正常运行
### 前端检查
- [ ] app.html包含验证码UI
- [ ] app.html版本号已更新
- [ ] app.js包含withCredentials配置
- [ ] app.js包含验证码逻辑
- [ ] 浏览器缓存已清除
### Nginx检查
- [ ] location /api包含proxy_set_header Cookie
- [ ] location /api包含proxy_pass_header Set-Cookie
- [ ] nginx -t 测试通过
- [ ] nginx已重新加载
### 功能测试
- [ ] 第1-2次登录失败不显示验证码
- [ ] 第3次登录失败显示验证码
- [ ] 验证码图片可以正常显示
- [ ] 点击验证码可以刷新
- [ ] 输入正确验证码可以通过验证
- [ ] 输入错误验证码提示错误
- [ ] 管理员登录也受验证码保护
- [ ] 登录成功后验证码自动隐藏
### API测试
- [ ] GET /api/captcha 返回SVG图片
- [ ] GET /api/captcha 返回Set-Cookie响应头
- [ ] POST /api/login 接收captcha参数
- [ ] POST /api/login 验证验证码
- [ ] POST /api/login 携带Cookie请求头
---
## 🎓 技术要点总结
### Session管理
```javascript
// 关键配置
session({
secret: 'your-secret',
resave: false,
saveUninitialized: true, // ⚠️ 必须为true
cookie: {
sameSite: 'lax', // ⚠️ 必须设置
httpOnly: true,
maxAge: 10 * 60 * 1000
}
})
```
### Axios配置
```javascript
// 全局配置
axios.defaults.withCredentials = true; // ⚠️ 必须设置
```
### Nginx配置
```nginx
location /api {
# ... 其他配置 ...
# ⚠️ 以下两行必须添加
proxy_set_header Cookie $http_cookie;
proxy_pass_header Set-Cookie;
}
```
### 验证码生成
```javascript
const svgCaptcha = require('svg-captcha');
const captcha = svgCaptcha.create({
size: 4, // 4位数字
noise: 2, // 干扰线
color: true, // 彩色
charPreset: '0123456789' // 只用数字
});
req.session.captcha = captcha.text.toLowerCase();
req.session.captchaTime = Date.now();
```
### 验证码验证
```javascript
// 检查是否需要验证码
const needCaptcha = ipFailures >= 2 || usernameFailures >= 2;
if (needCaptcha) {
// 验证验证码
const sessionCaptcha = req.session.captcha;
const captchaTime = req.session.captchaTime;
// 检查过期5分钟
if (Date.now() - captchaTime > 5 * 60 * 1000) {
return res.status(400).json({
success: false,
message: '验证码已过期'
});
}
// 验证是否匹配
if (captcha.toLowerCase() !== sessionCaptcha) {
return res.status(400).json({
success: false,
message: '验证码错误'
});
}
}
```
---
## 🔐 安全注意事项
1. **SESSION_SECRET**: 生产环境必须设置强随机值
2. **COOKIE_SECURE**: HTTPS环境必须设置为true
3. **ALLOWED_ORIGINS**: 必须配置CORS白名单
4. **JWT_SECRET**: 必须设置强随机值
5. **私人令牌**: 不要泄露到公开仓库
---
**文档版本**: v1.0
**最后更新**: 2025-11-21
**作者**: Claude Code
**状态**: ✅ 代码已完成并推送 | ⚠️ 生产环境待修复