# 玩玩云 - 验证码功能交接文档 > 创建时间: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 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 **状态**: ✅ 代码已完成并推送 | ⚠️ 生产环境待修复