diff --git a/UPDATE_SUMMARY_v1.1.0.md b/UPDATE_SUMMARY_v1.1.0.md new file mode 100644 index 0000000..06e3355 --- /dev/null +++ b/UPDATE_SUMMARY_v1.1.0.md @@ -0,0 +1,320 @@ +# 玩玩云 v1.1.0 更新总结 + +**发布日期**: 2025-11-13 +**版本**: v1.1.0 +**提交记录**: ac9f1c7 + +--- + +## 🎉 本次更新内容 + +### 1. 🔐 安全增强 - 防爆破保护系统 + +#### 登录防爆破保护 +- **限制策略**: 5次失败尝试/15分钟 +- **封锁时长**: 30分钟 +- **保护维度**: + - IP地址维度(防止同一IP多次尝试) + - 用户名维度(防止针对特定账号的攻击) +- **技术实现**: + - 新增 `RateLimiter` 类 + - 使用内存存储(TTL机制) + - 自动清理过期记录 + +#### 分享密码防爆破保护 +- **限制策略**: 10次失败尝试/10分钟 +- **封锁时长**: 20分钟 +- **保护维度**: IP + 分享码组合 +- **应用场景**: + - `/api/share/:code/verify` - 密码验证 + - 防止暴力破解分享密码 + +#### 反向代理支持 +- 支持读取 `X-Forwarded-For` 头 +- 正确识别真实客户端IP +- 适配 Nginx/Caddy 等反向代理 + +#### 安全日志 +```javascript +[防爆破] 拦截登录尝试 - IP: xxx.xxx.xxx.xxx, 原因: IP被封锁 +[防爆破] 封锁Key: login:username:admin, 失败次数: 5, 封锁时长: 30分钟 +[防爆破清理] 已清理 12 个过期尝试记录, 3 个过期封锁记录 +``` + +--- + +### 2. 🔧 部署优化 - 上传工具修复 + +#### 问题描述 +更新脚本执行 `git pull` 时会删除 `upload-tool` 目录,但由于 `.gitignore` 排除了 `dist/*.exe`,导致更新后上传工具丢失。 + +#### 解决方案 +在 `install.sh` 更新流程中添加检查逻辑: + +```bash +# 检查并重新下载上传工具(如果需要) +if [[ ! -f "${PROJECT_DIR}/upload-tool/dist/玩玩云上传工具.exe" ]]; then + print_info "检测到上传工具丢失,正在重新下载..." + build_upload_tool +else + FILE_SIZE=$(stat -c%s "${PROJECT_DIR}/upload-tool/dist/玩玩云上传工具.exe") + if [[ $FILE_SIZE -lt 30000000 ]]; then + print_warning "上传工具文件大小异常,正在重新下载..." + build_upload_tool + fi +fi +``` + +#### 功能特性 +- ✅ 自动检测上传工具是否存在 +- ✅ 验证文件大小确保完整性(>30MB) +- ✅ 自动从直链下载:`http://a.haory.top/e/e82/玩玩云上传工具.exe` +- ✅ 最多重试3次,确保下载成功 + +--- + +### 3. 🎨 界面优化 + +#### 首页更新 +- **版本标识**: "v1.0 生产就绪版本" → "版本号 V1.0" +- **功能描述**: 明确说明支持 SFTP 和本地存储双模式 +- **统计卡片**: + - 移除 "100%开源免费" + - 移除 "Docker 一键部署" + - 新增 "双模式 - SFTP + 本地存储" +- **页脚简化**: 移除不可点击的导航链接 + +#### 功能说明优化 +- 将 "流式下载" 更名为 "灵活下载" +- 明确说明本地存储模式不是流式中转 + +--- + +## 📊 提交记录 + +### Commit 1: 防爆破保护 +``` +commit c439966 +feat: 添加登录和分享密码防爆破保护 + +- 新增RateLimiter类实现基于IP和用户名的限流 +- 登录接口: 5次失败/15分钟后封锁30分钟 +- 分享密码: 10次失败/10分钟后封锁20分钟 +- 支持X-Forwarded-For反向代理 +- 自动清理过期记录 +- 详细的安全日志记录 +``` + +**变更文件**: +- `backend/server.js`: +233行, -1行 + +### Commit 2: 上传工具修复 +``` +commit 72063c5 +fix: 修复更新脚本导致上传工具丢失的问题 + +- 在更新流程中添加上传工具完整性检查 +- 如果上传工具丢失或文件大小异常,自动重新下载 +- 使用已有的build_upload_tool函数从直链下载 +- 验证文件大小确保下载完整(>30MB) +``` + +**变更文件**: +- `install.sh`: +16行 + +### Commit 3: 版本发布 +``` +commit ac9f1c7 +chore: 发布 v1.1.0 版本 + +新增功能: +- 登录和分享密码防爆破保护 +- 更新脚本自动检测和修复上传工具 +- 首页界面优化 +``` + +**变更文件**: +- `VERSION.txt`: +46行, -26行 + +--- + +## 🧪 测试建议 + +### 1. 防爆破保护测试 + +**登录限流测试**: +```bash +# 连续5次错误密码登录 +curl -X POST http://localhost:40001/api/login \ + -H "Content-Type: application/json" \ + -d '{"username":"admin","password":"wrongpass"}' + +# 第6次应返回 429 状态码 +# 响应: {"success":false,"message":"登录尝试过多,请在 30 分钟后重试","blocked":true} +``` + +**分享密码限流测试**: +```bash +# 连续10次错误密码 +for i in {1..11}; do + curl -X POST http://localhost:40001/api/share/XXXXX/verify \ + -H "Content-Type: application/json" \ + -d '{"password":"wrongpass"}' + echo "" +done + +# 第11次应返回 429 状态码 +``` + +### 2. 上传工具修复测试 + +```bash +# 1. 备份当前上传工具 +mv upload-tool/dist/玩玩云上传工具.exe /tmp/backup.exe + +# 2. 执行更新 +./install.sh +# 选择选项 7: 更新系统 + +# 3. 验证上传工具已自动恢复 +ls -lh upload-tool/dist/玩玩云上传工具.exe +# 应显示文件大小约 43MB +``` + +### 3. 反向代理测试 + +Nginx配置示例: +```nginx +location /api/ { + proxy_pass http://localhost:40001; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; +} +``` + +验证日志中显示的是真实客户端IP而非代理IP。 + +--- + +## 📝 升级指南 + +### 从 v1.0.0 升级到 v1.1.0 + +#### 方法一: 使用安装脚本(推荐) +```bash +cd /opt/vue-driven-cloud-storage +./install.sh +# 选择选项 7: 更新系统 +``` + +脚本会自动: +1. 停止现有服务 +2. 拉取最新代码 +3. 检测并重新下载上传工具(如需要) +4. 更新依赖 +5. 重启服务 + +#### 方法二: 手动更新 +```bash +# 1. 停止服务 +pm2 stop vue-driven-cloud-storage-backend + +# 2. 备份数据 +cp -r backend/data /tmp/backup-data + +# 3. 拉取代码 +git pull origin master + +# 4. 检查上传工具 +ls -lh upload-tool/dist/玩玩云上传工具.exe +# 如果不存在或小于30MB,重新下载: +wget -O upload-tool/dist/玩玩云上传工具.exe \ + http://a.haory.top/e/e82/玩玩云上传工具.exe + +# 5. 重启服务 +pm2 restart vue-driven-cloud-storage-backend +``` + +--- + +## 🔍 技术细节 + +### RateLimiter 实现原理 + +```javascript +class RateLimiter { + constructor(options) { + this.maxAttempts = options.maxAttempts || 5; + this.windowMs = options.windowMs || 15 * 60 * 1000; + this.blockDuration = options.blockDuration || 30 * 60 * 1000; + this.attempts = new Map(); // 尝试记录 + this.blockedKeys = new Map(); // 封锁记录 + } + + recordFailure(key) { + // 检查是否已封锁 + if (this.isBlocked(key)) { + return { blocked: true, ... }; + } + + // 记录失败尝试 + let info = this.attempts.get(key) || { count: 0, windowEnd: ... }; + info.count++; + + // 达到阈值,进行封锁 + if (info.count >= this.maxAttempts) { + this.blockedKeys.set(key, { expiresAt: ... }); + return { blocked: true, ... }; + } + + return { blocked: false, remainingAttempts: ... }; + } + + recordSuccess(key) { + // 认证成功,清除所有记录 + this.attempts.delete(key); + this.blockedKeys.delete(key); + } +} +``` + +### 中间件应用 + +```javascript +// 登录接口 +app.post('/api/login', + loginRateLimitMiddleware, // 添加限流中间件 + [...validators], + async (req, res) => { + // 验证失败 + if (!user || !passwordCorrect) { + loginLimiter.recordFailure(req.rateLimitKeys.ipKey); + loginLimiter.recordFailure(req.rateLimitKeys.usernameKey); + return res.status(401).json({...}); + } + + // 验证成功 + loginLimiter.recordSuccess(req.rateLimitKeys.ipKey); + loginLimiter.recordSuccess(req.rateLimitKeys.usernameKey); + return res.json({...}); + } +); +``` + +--- + +## 🐛 已知问题 + +无已知问题。 + +--- + +## 📧 反馈与支持 + +如遇到问题,请通过以下方式反馈: +- Gitee Issues: https://gitee.com/yu-yon/vue-driven-cloud-storage/issues +- 查看日志: `pm2 logs vue-driven-cloud-storage-backend` + +--- + +**感谢使用玩玩云!** 🎉