Commit Graph

259 Commits

Author SHA1 Message Date
816a712cd8 📋 添加完整交接文档 - 验证码功能 2025-11-21 17:08:33 +00:00
3ef0fa844a 📖 添加验证码快速修复指南 2025-11-21 17:05:22 +00:00
225c3a5ded 🔧 更新install.sh - 添加Nginx Cookie传递配置
## 修改说明
install.sh生成的Nginx配置中缺少Cookie传递设置,
导致验证码session无法正常工作。

## 修改内容

### install.sh
在3处 `location /api` 配置中添加Cookie传递:

```nginx
# Cookie传递配置(验证码session需要)
proxy_set_header Cookie $http_cookie;
proxy_pass_header Set-Cookie;
```

修改位置:
- 行2383: HTTP配置(configure_nginx_http_first)
- 行2665: HTTPS配置(configure_nginx_final)
- 行2802: 虚拟主机配置

### 新增文件

1. **fix_install_sh.sh**
   - 自动化修改脚本
   - 备份原文件后自动添加Cookie配置
   - 可重复运行(检测已修改则跳过)

2. **INSTALL_SH_UPDATE.md**
   - 详细的修改说明文档
   - 手动修改方法
   - 验证和应用指南

## 使用方法

### 新部署
直接运行修改后的install.sh即可

### 自动修改
```bash
./fix_install_sh.sh
```

### 已部署服务
需要手动更新Nginx配置:
```bash
vim /etc/nginx/conf.d/玩玩云.conf
# 在 location /api 块中添加Cookie配置
nginx -t
nginx -s reload
```

## 配套修复
此修改配合以下提交才能完整工作:
- 后端session配置 (7ce9d95)
- 前端axios配置 (83773ef)
- nginx/nginx.conf (5f3fd38)
- install.sh (本提交)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 16:54:26 +00:00
5f3fd38bb1 🐛 修复Nginx Cookie传递问题 - 验证码Session关键修复
## 问题根源(终于找到了!)
Nginx反向代理默认不会正确传递Cookie,导致:
1. 后端设置的 Set-Cookie 响应头被Nginx丢弃
2. 前端发送的 Cookie 请求头无法到达后端
3. 验证码session完全无法工作

## 症状
- 验证码一直提示"已过期"
- 即使前端配置了 withCredentials: true 也无效
- 浏览器看不到 captcha.sid cookie

## 修复方案

在 nginx.conf 的 /api/ location 块中添加:

```nginx
# Cookie传递配置(验证码session需要)
proxy_set_header Cookie $http_cookie;
proxy_pass_header Set-Cookie;
```

### 配置说明

1. `proxy_set_header Cookie $http_cookie;`
   - 将浏览器发送的Cookie转发给后端
   - 后端可以读取验证码session

2. `proxy_pass_header Set-Cookie;`
   - 将后端的Set-Cookie响应头传递给浏览器
   - 浏览器可以保存验证码session cookie

## 完整的验证码工作流程

1. **验证码生成**:
   ```
   浏览器 → Nginx → 后端生成验证码和session
   后端 → Set-Cookie: captcha.sid=xxx → Nginx → 浏览器保存
   ```

2. **验证码验证**:
   ```
   浏览器(带Cookie) → Nginx → 后端读取session验证
   ```

## 部署说明

### Docker环境
```bash
docker-compose down
docker-compose up -d
```

### 手动Nginx
```bash
nginx -t  # 测试配置
nginx -s reload  # 重新加载
```

## 验证方法

1. 清除浏览器Cookie
2. F12 → Network → 清除日志
3. 访问登录页,输错密码2次
4. 查看 /api/captcha 响应头应该有 Set-Cookie
5. 查看 /api/login 请求头应该有 Cookie: captcha.sid=xxx
6. 输入验证码应该能正常通过

## 相关提交

此修复配合以下提交才能完整工作:
- 后端session配置修复 (7ce9d95)
- 前端axios withCredentials配置 (83773ef)
- Nginx Cookie传递配置 (本提交)

三个修复缺一不可!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 16:49:38 +00:00
fca00aa9fa 🔄 更新前端版本号 - 强制刷新浏览器缓存
## 问题
浏览器缓存了旧版本的app.js,新的axios配置无法生效

## 修改
app.js?v=20251110001 → app.js?v=20251121001

## 说明
版本号更新后,浏览器会自动下载新的app.js文件,
包含最新的axios withCredentials配置

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 16:46:58 +00:00
83773ef54e 🐛 修复验证码跨域Cookie传递问题
## 问题描述
验证码在生产环境(https://cs.workyai.cn)一直提示"验证码已过期"

## 根本原因
axios默认不携带credentials(包括cookies),导致:
1. 验证码生成时的session cookie无法被浏览器保存
2. 登录时无法读取到验证码session
3. SessionID不一致导致验证失败

## 修复方案
在mounted钩子中添加axios全局配置:
```javascript
axios.defaults.withCredentials = true;
```

这样所有axios请求都会携带cookies,包括:
- 验证码生成请求
- 登录验证请求
- 所有其他API请求

## 配合后端配置
后端已配置:
- CORS: credentials: true
- Session cookie: sameSite: 'lax'
- Session: saveUninitialized: true

## 测试说明
1. 清除浏览器Cookie
2. 访问 https://cs.workyai.cn
3. 输错密码2次触发验证码
4. 输入验证码应该能正常通过

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 16:42:37 +00:00
7ce9d95d44 🐛 修复验证码Session问题 - 验证码过期Bug修复
## 问题描述
用户输入验证码后一直提示"验证码已过期"

## 根本原因
Session配置问题导致验证码无法正确保存和读取:
1. saveUninitialized: false 导致验证码请求时session不会被创建
2. 缺少 sameSite 属性导致某些情况下cookie无法正确传递

## 修复方案

### Session配置优化
- saveUninitialized: false → true (确保验证码请求时创建session)
- 添加 name: 'captcha.sid' (自定义session cookie名称)
- 添加 sameSite: 'lax' (防止CSRF同时确保同站请求携带cookie)

### 验证码生成API增强
- 添加 req.session.save() 确保session立即保存
- 添加调试日志输出SessionID和验证码内容

### 登录API调试
- 添加详细的验证码验证日志
- 输出SessionID、失败次数、验证码匹配情况
- 帮助快速定位问题

## 测试建议
1. 清除浏览器Cookie
2. 输错密码2次触发验证码
3. 查看后端日志确认SessionID一致
4. 输入正确验证码应该能通过验证

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 16:39:38 +00:00
61c99ce5c0 添加登录验证码功能 - 增强系统安全性
## 新增功能
- 密码输错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>
2025-11-21 16:32:32 +00:00
619b965cf8 🐛 修复分享页下载文件时页面闪动问题
- 问题:使用window.open()下载文件会导致页面短暂失焦,产生闪动效果
- 修复:改用隐藏的<a>标签触发下载,避免打开新标签页
- 新增triggerDownload()方法处理文件下载
- 影响文件:frontend/share.html (line 744-795)
2025-11-18 18:10:03 +08:00
7d1cb7b506 🐛 修复文件夹分享bug - 只显示第一个文件的问题
问题:
- 分享文件夹时,分享链接只显示文件夹内第一个文件
- 原因:前端无论文件还是文件夹都使用share_type='file'
- 后端对非file类型的分享路径处理不正确

修复方案:
1. 前端修改(frontend/app.js):
   - shareFileForm添加isDirectory字段标记是否为文件夹
   - openShareFileModal设置isDirectory值
   - createShareFile根据isDirectory设置正确的share_type
     * 文件: share_type='file'
     * 文件夹: share_type='directory'

2. 后端修改(backend/database.js):
   - 修复ShareDB.create中的sharePath逻辑
   - file类型:使用file_path(单文件路径)
   - directory类型:使用file_path(文件夹路径)
   - all类型:使用'/'(根目录)

测试:
- 分享单个文件:正常显示单个文件
- 分享文件夹:正常显示文件夹内所有文件
- 分享所有文件:正常显示根目录所有文件
2025-11-18 17:58:31 +08:00
746539a067 🔒 修复CORS逻辑 - 正确处理同源请求
问题:
- 第一次修复过于严格,拒绝了所有无Origin头的请求
- 导致浏览器的同源请求被拒绝,网站完全无法使用

修复方案:
- 允许无Origin头的请求(同源请求不触发CORS)
- 严格验证带Origin头的跨域请求(必须在白名单中)
- 拒绝所有未授权的跨域请求

文件修改:
- backend/server.js: 修正CORS中间件逻辑(第48-63行)

测试:
- 同源请求正常工作
- 恶意跨域请求被拒绝
- API返回正确的状态码(不再是500错误)
2025-11-18 17:08:22 +08:00
e026c13fd3 🔒 修复CORS严重安全漏洞 & 增强Nginx安全配置
## 关键修复

### 1. 修复backend/server.js的CORS漏洞 ⚠️ CRITICAL
**问题**: 原代码 `if (!origin || allowedOrigins.includes(origin))`
        会允许所有没有Origin头的请求通过,导致恶意请求绕过CORS保护

**修复**: 严格白名单模式
```javascript
// 只允许白名单中的域名
if (origin && allowedOrigins.includes(origin)) {
  callback(null, true);
} else {
  // 拒绝所有其他请求
  callback(new Error('CORS策略不允许来自该来源的访问'));
}
```

**影响**:
-  阻止所有恶意域名的跨域访问
-  保护JWT token不被窃取
-  从63.6%预计提升到90%+安全评分

### 2. 增强install.sh中的Nginx安全配置

在所有三个nginx配置函数中添加了完整的安全规则:
- `configure_nginx_http_first()` - 初始HTTP配置
- `configure_nginx_http()` - 纯HTTP模式
- `configure_nginx_https()` - HTTPS模式

**新增安全配置**:
```nginx
# 安全响应头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # HTTPS专用

# 隐藏Nginx版本
server_tokens off;

# 禁止访问隐藏文件 (.git, .env等)
location ~ /\. {
    deny all;
    return 404;
}

# 禁止访问敏感文件
location ~ \.(env|git|config|key|pem|crt|sql|bak|backup|old|log)$ {
    deny all;
    return 404;
}
```

**防护效果**:
-  阻止访问 /.env, /.git/config
-  阻止访问备份文件 .bak, .sql
-  防止点击劫持、XSS、MIME嗅探攻击
-  强制HTTPS(HTTPS环境下)
-  隐藏服务器信息

## 部署方法

在服务器上执行:
```bash
cd /var/www/wanwanyun
git pull origin master
bash install.sh --repair  # 重新生成Nginx配置
# 或者手动
pm2 restart wanwanyun-backend
nginx -t && systemctl reload nginx
```

然后运行安全测试验证:
```bash
node security-test.js
```

预期改进:
- CORS测试: 只有cs.workyai.cn被允许 
- 敏感文件: 全部返回404 
- 安全响应头: 全部检测到 
- 安全评分: 63.6% → 90%+ 🎯

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 16:58:19 +08:00
ada9afa396 🛡️ 添加更新时的安全配置自动检查和修复
解决了使用install.sh更新时,旧的不安全CORS配置仍然保留的问题。

## 新增功能

### 自动安全配置检查
更新时会自动检查 backend/.env 中的安全配置:

1. **CORS配置检查**
   - 检测 ALLOWED_ORIGINS=* (不安全)
   - 自动从Nginx配置读取域名
   - 自动检测HTTP/HTTPS协议
   - 提示用户确认并自动修复

2. **环境变量检查**
   - 检查NODE_ENV是否设置为production
   - 给出安全建议

### 工作流程

当执行 `bash install.sh --update` 时:

```bash
检查安全配置...
⚠️  检测到不安全的CORS配置: ALLOWED_ORIGINS=*

这是一个严重的安全风险!攻击者可以从任何域名访问你的API。

检测到域名: cs.workyai.cn
建议将CORS设置为: https://cs.workyai.cn

是否自动修复CORS配置?[y/n]:
```

### 修复机制

-  自动备份原配置到 .env.backup.YYYYMMDD_HHMMSS
-  智能检测HTTP/HTTPS
-  从Nginx配置读取域名
-  用户确认后自动修改
-  如果无法自动修复,给出手动修复指引

### 兼容性

-  不影响安全的现有配置
-  只修复明确不安全的配置(ALLOWED_ORIGINS=*)
-  提供备份,可随时回滚

## 使用方法

```bash
# 更新项目(会自动检查安全配置)
bash install.sh --update

# 或者使用交互式菜单
bash install.sh
# 选择 [2] 更新/升级
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 16:37:39 +08:00
32429334ab 🔒 重大安全更新:修复CORS、XSS、敏感文件暴露等漏洞
本次更新修复了安全测试中发现的所有严重问题,大幅提升系统安全性。

## 修复的安全问题

### 1. CORS跨域配置漏洞 ⚠️ 严重
**问题**: 默认允许所有域名访问(ALLOWED_ORIGINS=*)
**修复**:
- 默认值改为空数组,生产环境必须明确配置域名白名单
- 未配置时拒绝所有跨域请求(生产环境)
- 开发环境仅允许localhost访问

### 2. XSS跨站脚本攻击 ⚠️ 严重
**问题**: 用户输入未过滤,可注入恶意脚本
**修复**:
- 添加XSS过滤中间件,自动转义所有POST/PUT请求的用户输入
- 过滤 <, >, ', " 等危险字符
- 递归处理嵌套对象和数组

### 3. 缺少安全响应头 ⚠️ 重要
**问题**: 缺少X-Frame-Options等安全响应头
**修复**:
- X-Frame-Options: SAMEORIGIN (防止点击劫持)
- X-Content-Type-Options: nosniff (防止MIME嗅探)
- X-XSS-Protection: 1; mode=block
- Strict-Transport-Security (HTTPS环境)
- Content-Security-Policy (内容安全策略)
- 隐藏X-Powered-By和Server版本信息

### 4. 敏感文件暴露风险 ⚠️ 严重
**问题**: .env、.git等敏感文件可能被访问
**修复**:
- Nginx配置禁止访问以.开头的隐藏文件
- 禁止访问.env、.git、.config、.key、.pem等敏感文件
- 更新.gitignore,防止敏感文件提交到代码仓库
- 添加证书、密钥等文件类型到忽略列表

## 代码改动

### backend/server.js
- 修改CORS默认配置,移除危险的 * 通配符
- 添加安全响应头中间件
- 添加XSS过滤中间件(sanitizeInput函数)
- 生产环境强制检查ALLOWED_ORIGINS配置

### nginx/nginx.conf
- 添加安全响应头配置
- 禁止访问隐藏文件和敏感文件的location规则
- 隐藏Nginx版本号(server_tokens off)

### .gitignore
- 添加敏感配置文件保护(.env.local, config.json等)
- 添加证书和密钥文件类型(.key, .pem, .crt等)

### deploy.sh
- 修改默认配置,移除ALLOWED_ORIGINS=*
- 添加安全警告提示

## 部署说明

⚠️ **重要**: 更新后必须配置ALLOWED_ORIGINS环境变量!

### 手动部署
编辑 `backend/.env` 文件:
```bash
ALLOWED_ORIGINS=https://cs.workyai.cn
NODE_ENV=production
```

### 使用install.sh部署
脚本会自动根据域名配置ALLOWED_ORIGINS

## 测试结果

修复前安全评分: 57.6% (14个安全问题)
修复后预期评分: 90%+ (预计解决12+个问题)

## 兼容性

-  向后兼容,不影响现有功能
-  开发环境自动允许localhost访问
- ⚠️ 生产环境必须配置ALLOWED_ORIGINS(否则无法访问)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 16:29:44 +08:00
eee07d3820 优化检测逻辑,减少误判
修复了正常访问时也提示"检测到开发者工具"的问题。

核心改进:
1. 提高检测阈值,避免误判
   - 窗口尺寸差异从160px提高到200px
   - 要求console和其他方法同时检测到才触发
2. 降低检测频率
   - 从每1秒改为每2秒检测一次
   - 减少性能消耗和误判概率
3. 严格判定条件
   - console检测为主要依据
   - debugger和窗口尺寸作为辅助确认

检测逻辑:
- consoleOpen && (debuggerPause || windowSizeAbnormal)
- 必须console明确检测到,且至少有一个辅助条件满足

说明:
前端防护无法完全阻止技术人员查看源代码(Network面板、
右键查看源代码等),但可以有效防止普通用户使用F12。
真正的安全依赖于后端验证和权限控制。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 21:01:57 +08:00
019b213178 终极防护:在页面渲染前检测开发者工具
解决了用户打开控制台后能看到源代码的问题。

核心改进:
1. 将检测代码移到<head>最前面,在页面渲染前执行
2. 使用document.write()立即阻止页面加载
3. 检测到开发者工具时throw Error阻止后续脚本
4. 删除底部重复的检测代码,统一在头部处理
5. 优化检测逻辑,使用console.log触发toString

工作原理:
- 页面加载第一时间就执行检测
- 如果检测到开发者工具,立即用document.write替换页面
- throw Error阻止后续所有脚本和Vue应用加载
- 用户无法看到真实页面内容和源代码

测试场景:
 先打开F12再访问 → 立即显示警告,页面不加载
 访问后按F12 → 快捷键被禁用
 调试模式 → 所有保护自动禁用

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 20:40:13 +08:00
4324d886d8 重构开发者工具检测机制 - 使用多重检测方法
修复了控制台在其他页面打开后仍能在本站显示的问题。

核心改进:
1. 新增Console对象toString检测(最有效)
2. 优化debugger暂停时间检测
3. 保留窗口尺寸检测作为补充
4. 综合多种方法,提高检测准确率
5. 页面加载时立即执行检测
6. 持续监控确保实时防护

检测原理:
- console.log会触发对象的toString方法
- 当控制台打开时,这个方法会被调用
- 通过标志位检测到调用,即可判断控制台已打开

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 20:33:01 +08:00
69e864bcfb 增强开发者工具检测防护功能
修复了用户可以在其他页面先打开F12控制台,然后访问网站时绕过禁用的问题。

主要改进:
- 页面加载时立即检测开发者工具是否已打开
- 新增 debugger 断点检测机制,检测更灵敏
- 检测到开发者工具时显示美观的全屏警告页面
- 防止重复警告显示
- 调试模式下所有保护机制自动禁用

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 19:57:02 +08:00
WanWanYun
cb4bf0e8d5 fix: 修复文件夹详情功能点击无反应的问题
问题描述:
- 右键文件夹 → 点击"查看详情"
- 菜单关闭但没有任何反应
- 详情弹窗不显示

根本原因:
在 contextMenuAction(action) 的 switch 语句中
**缺少 case 'info': 分支**

代码分析:
```javascript
contextMenuAction(action) {
  switch (action) {
    case 'preview': ...
    case 'download': ...
    case 'rename': ...
    case 'share': ...      //  直接跳到share,跳过了info
    case 'delete': ...
  }
}
```

修复方案:
在 rename 和 share 之间添加:
```javascript
case 'info':
  this.showFolderInfo(this.contextMenuFile);
  break;
```

修复后流程:
1. 右键文件夹 → "查看详情"
2. 触发 contextMenuAction('info')
3. 执行 showFolderInfo(file)
4. 调用后端 API: POST /api/files/folder-info
5. 显示详情弹窗(大小、文件数、子文件夹数)

之前为什么漏掉:
添加showFolderInfo方法时,忘记在contextMenuAction中注册该action

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 00:22:40 +08:00
WanWanYun
a9b269af12 fix: 修复更新时无法选择是否保留上传工具的问题
问题描述:
- 显示了选择菜单,但read命令直接跳过
- 无法输入选择,直接使用默认值1
- 用户想选择2也无法输入

原因分析:
- update流程中标准输入可能被重定向或被其他命令消耗
- read命令从stdin读取时可能读到空输入
- 导致直接使用默认值

解决方案:
使用 `< /dev/tty` 强制从终端读取:
```bash
read -p "▶ 请选择 [1/2, 默认:1]: " KEEP_UPLOAD_TOOL < /dev/tty
```

工作原理:
- /dev/tty: 当前终端设备
- < /dev/tty: 强制从终端读取输入
- 即使stdin被重定向,仍能从终端获取用户输入

测试建议:
运行 bash install.sh update 时:
1. 显示选择菜单
2. 等待用户输入
3. 输入1: 保留工具
4. 输入2: 重新下载
5. 直接回车: 使用默认值1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 00:21:22 +08:00
WanWanYun
2e0376e7e5 fix: 修复更新脚本选择"不保留上传工具"无法触发重新下载的问题
问题描述:
- 更新时选择"2) 删除并重新下载"
- 但实际上只是删除并复制了新的upload-tool目录
- 没有触发后续的build_upload_tool()重新下载
- 导致用户无法获取最新的上传工具

原因分析:
- else分支(选择2)只做了 rm + cp 操作
- 复制的新目录中没有dist/玩玩云上传工具.exe
- 但后续检查逻辑看的是文件是否存在和大小
- 如果目录结构存在,即使文件不存在也不会重新下载

修复方案:
在else分支最后添加:
```bash
# 删除dist目录以触发后续重新下载
rm -rf "${PROJECT_DIR}/upload-tool/dist"
```

修复后逻辑:
1. 选择"1"保留:
   - 备份dist目录
   - 更新upload-tool脚本文件
   - 恢复dist目录
   - 跳过后续下载

2. 选择"2"重新下载:
   - 删除整个upload-tool
   - 复制新的upload-tool
   - **删除dist目录**  NEW
   - 触发后续build_upload_tool()重新下载

验证:
后续update_install_dependencies后面的检查:
```bash
if [[ ! -f "${PROJECT_DIR}/upload-tool/dist/玩玩云上传工具.exe" ]]; then
    build_upload_tool  #  会被触发
fi
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 00:19:13 +08:00
WanWanYun
0bb7bd5219 fix: 修复文件夹详情功能 + 添加文件夹分享
修复内容:

1. 【文件夹详情无反应】
   - 问题: folder-info API中变量名冲突
   - 原因: API参数名'path'与Node.js的'path'模块冲突
   - 具体: 第1193行 `const itemPath = path.join(dirPath, item.name)`
            这里的path被当作API参数(字符串)而不是模块
   - 修复:
     * API参数改为 `const { path: dirPath, folderName }`
     * 使用dirPath替代path
     * countFiles函数参数改为countDirPath避免混淆
   - 效果: 查看详情功能现在正常工作

新功能:

2. 【文件夹分享】
   - 移除分享功能的文件限制
   - 右键菜单"分享"选项对文件和文件夹都显示
   - 文件夹分享后可访问该文件夹下所有文件
   - 与现有分享API完全兼容(share_type支持file和all)

技术细节:
- backend/server.js:
  * 第1138行: path参数改为dirPath
  * 第1186行: countFiles函数参数改为countDirPath
  * 第1193行: 使用path.join正确引用模块

- frontend/app.html:
  * 移除 `v-if="!contextMenuFile.isDirectory"` 限制
  * 文件夹也显示"分享"菜单项

使用方式:
1. 右键文件夹 → "查看详情" → 显示大小、文件数、子文件夹数
2. 右键文件夹 → "分享" → 分享整个文件夹

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 00:15:43 +08:00
WanWanYun
e10ff04166 feat: 优化更新流程 - 添加保留上传工具选项
问题背景:
- 之前每次更新都会删除并重新下载上传工具(43MB)
- 重新下载耗时长(1-2分钟),且可能因网络问题失败
- 但如果不删除,万一上传工具有更新也无法获取

优化方案:
在更新流程中添加用户选择:

更新上传工具逻辑:
1. 检测是否已存在上传工具可执行文件
2. 验证文件大小(>30MB为有效)
3. 如果存在有效工具,显示选择菜单:

   ╔════════════════════════════════════════════════════════════╗
   ║                   上传工具更新选项                         ║
   ╠════════════════════════════════════════════════════════════╣
   ║  1) 保留现有上传工具(推荐,节省下载时间)                ║
   ║  2) 删除并重新下载(如果工具有更新)                      ║
   ╚════════════════════════════════════════════════════════════╝

选项1 - 保留现有工具:
- 创建临时目录备份dist/玩玩云上传工具.exe
- 更新upload-tool目录的脚本文件
- 恢复备份的可执行文件
- 优点: 节省1-2分钟下载时间,避免网络问题

选项2 - 重新下载:
- 删除整个upload-tool目录
- 在后续步骤重新下载最新工具
- 适用: 官方发布了新版本上传工具

默认行为:
- 默认选项1(保留),直接回车即可
- 如果现有文件大小异常(<30MB),自动重新下载
- 如果不存在上传工具,直接复制新目录

技术改动:
- install.sh update_pull_latest_code() 函数
- 添加用户交互选择逻辑
- 添加文件大小验证
- 添加备份和恢复逻辑

使用建议:
- 日常更新: 选择"1"保留,节省时间
- 重大版本更新: 选择"2"重新下载,确保最新

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 00:11:17 +08:00
WanWanYun
f64f86cd78 fix: 修复文件夹右键菜单问题 + 新增文件夹详情功能
修复内容:

1. 【文件夹右键菜单无法显示】
   - 问题: showFileContextMenu() 中仍有 `if (file.isDirectory) return` 阻止代码
   - 原因: 之前的修复脚本替换失败,代码仍在
   - 修复: 手动移除这行限制代码
   - 效果: 文件夹现在可以正常右键操作(重命名、删除、查看详情)

新功能:

2. 【文件夹详情查看】
   后端API (POST /api/files/folder-info):
   - 接收参数: path(当前路径), folderName(文件夹名称)
   - 计算文件夹总大小(递归统计所有文件)
   - 统计文件数量和子文件夹数量
   - 返回数据: name, path, size, fileCount, folderCount
   - 仅支持本地存储

   前端功能:
   - 右键菜单新增"查看详情"选项(仅文件夹显示)
   - 详情弹窗显示:
     * 文件夹名称
     * 文件夹路径
     * 总大小(格式化显示)
     * 文件数量
     * 子文件夹数量
   - 加载中状态提示
   - 错误处理和提示

使用方式:
1. 右键点击任意文件夹
2. 选择"查看详情"
3. 弹窗显示文件夹统计信息

技术改动:
- backend/server.js: +100行 (新增folder-info API)
- frontend/app.html: +40行 (详情弹窗UI + 菜单项)
- frontend/app.js: +30行 (状态 + showFolderInfo方法)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 00:07:21 +08:00
WanWanYun
560b90f7f7 fix: 修复文件夹功能的多个严重bug
问题修复:

1. 【文件夹无法重命名和删除】
   - 原因: showFileContextMenu 函数中 `if (file.isDirectory) return` 阻止了文件夹显示右键菜单
   - 修复: 移除这个限制,允许文件夹显示右键菜单
   - 效果: 文件夹现在可以右键重命名和删除

2. 【进入文件夹后无法返回上一页】
   - 原因: 页面没有路径导航条(面包屑导航)
   - 修复: 在文件列表上方添加完整的路径导航组件
   - 功能:
     * 显示当前路径层级
     * 点击路径中的任意层级可快速跳转
     * "返回上一级"按钮
     * "返回根目录"按钮
   - 新增 navigateUp() 方法处理返回上一级

3. 【上传文件到子文件夹路径错误(undefined文件夹)】
   - 原因: loadFiles() 调用时未传递 path 参数,导致 currentPath 变为 undefined
   - 修复:
     * loadFiles 开头添加安全检查: `this.currentPath = path || '/'`
     * createFolder 成功后调用 loadFiles 时传递 currentPath
   - 效果: 路径不会变成undefined,文件正确上传到当前目录

4. 【优化删除确认提示】
   - 旧提示: "只能删除空文件夹"(错误信息)
   - 新提示: "⚠️ 警告:文件夹内所有文件将被永久删除!"(准确描述行为)

技术改动:
- frontend/app.html: +15行 (路径导航条UI)
- frontend/app.js: +10行 (navigateUp方法 + 安全检查)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 23:59:08 +08:00
WanWanYun
de3b75c536 fix: 修复createFolder方法未正确添加到Vue methods中的问题
问题: 点击"新建文件夹"按钮时控制台报错 "createFolder is not a function"
原因: 之前使用正则表达式添加方法时没有成功匹配,导致方法未被添加
修复: 手动在renameFile方法后面正确添加createFolder方法

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 23:50:27 +08:00
WanWanYun
e5c932a351 feat: 新增本地存储文件夹管理功能
新功能概述:
- 支持在本地存储模式下创建文件夹
- 支持删除文件夹(递归删除)
- 支持重命名文件夹(已有功能,天然支持)
- 文件夹配额计算正确

后端改动:

1. 新增创建文件夹API (backend/server.js)
   - POST /api/files/mkdir
   - 参数: path(当前路径), folderName(文件夹名称)
   - 安全检查: 禁止特殊字符(/ \ .. :),防止路径遍历攻击
   - 仅限本地存储使用
   - 创建前检查文件夹是否已存在

2. 改进删除功能 (backend/storage.js)
   - LocalStorageClient.delete() 现在支持删除文件夹
   - 使用 fs.rmSync(path, { recursive: true }) 递归删除
   - 新增 calculateFolderSize() 方法计算文件夹总大小
   - 删除文件夹时正确更新配额使用情况

前端改动:

1. 新建文件夹按钮 (frontend/app.html)
   - 在"上传文件"按钮旁新增"新建文件夹"按钮
   - 仅本地存储模式显示

2. 新建文件夹弹窗 (frontend/app.html)
   - 简洁的创建表单
   - 支持回车键快速创建
   - 使用优化的弹窗关闭逻辑(防止拖动选择文本时误关闭)

3. 前端API调用 (frontend/app.js)
   - 新增 createFolderForm 状态
   - 新增 createFolder() 方法
   - 前端参数验证
   - 创建成功后自动刷新文件列表

4. 右键菜单优化 (frontend/app.html)
   - 文件夹不显示"下载"按钮(文件夹暂不支持打包下载)
   - 文件夹不显示"分享"按钮(分享单个文件夹暂不支持)
   - 文件夹支持"重命名"和"删除"操作

安全性:
- 文件夹名称严格验证,禁止包含 / \ .. : 等特殊字符
- 路径安全检查,防止目录遍历攻击
- 仅限本地存储模式使用(SFTP存储使用上传工具管理)

配额管理:
- 空文件夹不占用配额
- 删除文件夹时正确释放配额(计算所有子文件大小)
- 删除非空文件夹会递归删除所有内容

使用方式:
1. 登录后切换到本地存储模式
2. 点击"新建文件夹"按钮
3. 输入文件夹名称,点击创建
4. 双击文件夹进入,支持多级目录
5. 右键文件夹可重命名或删除

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 23:46:20 +08:00
WanWanYun
3977e72c9e fix: 修复弹窗交互问题和拖放上传UI重复显示
问题描述:
1. 弹窗点击外部关闭时,选择文本拖动鼠标到窗口外会误触关闭
2. 拖放文件上传的提示UI重复显示了两次

修复内容:

【弹窗交互优化】
- 将所有模态框的 @click 事件改为 @mousedown.self + @mouseup.self 组合
- 新增 handleModalMouseDown 和 handleModalMouseUp 方法
- 只有在同一个overlay元素上按下和释放鼠标时才关闭弹窗
- 解决了选择文本时拖动鼠标导致弹窗意外关闭的问题
- 受影响的弹窗:
  * 重命名文件弹窗
  * 分享所有文件弹窗
  * 分享单个文件弹窗
  * 忘记密码弹窗
  * 文件审查弹窗
  * 编辑存储权限弹窗

【拖放UI修复】
- 删除了重复的拖放上传提示层(原第670-677行)
- 保留文件列表区域内的拖放提示层(第711-718行)
- 现在拖放上传提示只显示一次

技术改进:
- mousedown.self: 只在overlay本身被按下时触发
- mouseup.self: 只在overlay本身被释放时触发
- 记录mousedown的目标,只有目标一致才执行关闭
- 提升了用户体验,避免误操作

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 22:32:50 +08:00
WanWanYun
eed2533f29 fix: 修复宝塔面板环境下install.sh安装脚本Nginx重载失败导致脚本闪退的问题
问题描述:
- 在宝塔面板环境下运行install.sh时,Nginx重载步骤会因为命令失败导致整个脚本闪退
- 由于脚本使用了 set -e,任何命令返回非0退出码都会导致脚本终止

修复内容:
1. configure_nginx_http_first 函数 (2408-2446行):
   - 移除可能失败的 /etc/init.d/bt restart 命令
   - 在所有Nginx命令前添加配置测试
   - 使用 || true 防止命令失败导致脚本退出
   - 优化错误提示,失败时不退出脚本

2. configure_nginx_final 函数 (2504-2538行):
   - 同样的修复逻辑应用到Nginx重载环节
   - 确保即使Nginx操作失败,脚本也能继续执行后续步骤

技术改进:
- 先测试Nginx配置再reload,避免配置错误导致服务中断
- reload失败时自动尝试重启Nginx
- 所有可能失败的命令都添加了错误处理
- 保留systemctl作为备用方案

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 19:31:52 +08:00
14ee0b4301 删除文件 test_rate_limit.sh 2025-11-14 17:28:12 +00:00
1fcf623059 删除文件 test_share_security.sh 2025-11-14 17:28:05 +00:00
a41a29d581 fix: 分享详情页显示到期时间
问题:
- 分享列表中显示的到期时间正确
- 但点进分享详情页时,到期时间只显示"永久有效"

原因:
- /api/share/:code/verify 接口返回的 share 对象中缺少 expires_at 字段
- 前端 shareInfo.expires_at 为 undefined,导致始终显示"永久有效"

修复:
- 在 server.js:1650 添加 expires_at 到响应数据中
- 现在分享详情页能正确显示到期时间

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 20:59:48 +08:00
f02bcee646 fix: 彻底修复所有表格和列表的文字溢出问题
关键修复:
1. 所有表格添加 table-layout: fixed
2. 表格列头添加明确的宽度百分比控制
3. 文件列表 - 修复 display: flex 导致的溢出
   - 将 flex 从 td 移到内部 div
   - 文件名使用 flex: 1 + min-width: 0
   - 所有图标添加 flex-shrink: 0
4. 分享列表 - 移除 max-width,使用列头宽度控制
5. 用户列表 - 移除 max-width,使用列头宽度控制

所有表格现在都能正确处理长文本,不会溢出容器

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 20:30:22 +08:00
d99568e418 fix: 修复前端所有页面的文字溢出问题
修复内容:
1. 文件列表 - 列表视图文件名溢出控制
2. 用户列表 - 用户名和邮箱溢出控制
3. 分享列表 - 文件路径和分享链接溢出控制

所有长文本现在都会正确显示省略号,不会导致UI布局异常

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 19:47:36 +08:00
f9d0a30d46 fix: 修复移动端分享列表长文件名导致UI溢出问题
## 问题
在移动端"我的分享"的列表视图下,长文件名会导致:
- 表格宽度被撑开
- 分享链接等内容溢出到容器外
- 页面布局错乱

## 修复
为分享列表的表格添加文字溢出处理:

1. 文件路径列:
   - 限制max-width: 200px
   - 超出部分显示省略号(text-overflow: ellipsis)
   - 鼠标悬停显示完整路径(title属性)

2. 分享链接列:
   - 限制max-width: 250px
   - 超出部分显示省略号
   - 鼠标悬停显示完整链接

## 其他位置检查
- 大图标视图已有溢出处理(-webkit-line-clamp: 2),无需修改
- 文件列表视图也已有完善的溢出处理

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 17:12:15 +08:00
8cda4c1a0b fix: 修复时区问题 - 使用本地时区存储和比较时间
## 问题
- 之前使用UTC时间存储expires_at
- 前端解析时当成本地时间,导致显示时间差8小时
- 例如: 数据库存 08:37 (UTC),前端显示 08:37 (本地),实际应该显示 16:37

## 修复
1. database.js create方法: 使用本地时区格式化时间
   - 使用 getFullYear/getMonth/getDate 等获取本地时间
   - 格式化为 YYYY-MM-DD HH:MM:SS (本地时间)

2. database.js findByCode方法: 使用本地时区比较
   - 改为 datetime('now', 'localtime')
   - 确保与存储的本地时间格式匹配

3. 调试日志也使用本地时区

## 效果
- 创建分享时,expires_at存储的是服务器本地时间
- 前端显示时间与服务器时间一致
- 过期判断使用本地时区,结果正确

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 16:46:26 +08:00
d56388dd29 fix: 修复分享过期时间格式导致的过滤失败问题
## 问题分析
通过调试日志发现,过期分享仍能访问的根本原因是:
- expires_at 存储格式: `2025-11-14T07:31:31.922Z` (ISO 8601)
- datetime('now') 返回格式: `2025-11-14 08:19:52` (SQLite格式)
- SQLite进行字符串比较时: 'T' (ASCII 84) > ' ' (ASCII 32)
- 导致条件 `expires_at > datetime('now')` 对已过期分享仍返回true

## 修复内容
1. database.js: 修改create方法,将expires_at转换为SQLite datetime格式
   - 旧格式: 2025-11-14T07:31:31.922Z
   - 新格式: 2025-11-14 07:31:31

2. fix_expires_at_format.js: 数据库修复脚本
   - 将已存在的ISO格式时间转换为SQLite格式
   - 确保历史数据也能正确过滤

## 部署步骤
```bash
cd /var/www/wanwanyun
git pull
cd backend
node fix_expires_at_format.js  # 修复历史数据
pm2 restart wanwanyun-backend   # 重启服务
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 16:25:31 +08:00
eaf9ad7bb1 debug: 添加详细的分享验证调试日志
## 调试内容
为了排查过期分享仍能访问的问题,添加了详细的调试日志:

### 1. database.js - ShareDB.findByCode()
- 记录调用时的参数和SQLite当前时间
- 记录SQL查询结果(是否找到、过期时间、分享类型)
- 便于对比JavaScript时间和SQLite时间

### 2. server.js - /api/share/:code/verify
- 记录请求时间戳、分享码、是否有密码、请求IP
- 记录findByCode的返回结果和过期状态

### 3. server.js - /api/share/:code/list
- 记录请求时间戳、分享码、子路径、密码状态
- 记录findByCode的返回结果和过期状态

## 使用方法
1. 管理员在管理后台开启调试模式
2. 访问分享链接 https://cs.workyai.cn/s/oSrhV9D3
3. 查看后端console日志输出

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 16:09:01 +08:00
bce225ec5c feat: 添加管理员可控的F12调试模式开关
## 功能说明
- 管理员登录后可在管理后台页面看到"调试模式"卡片
- 点击开关按钮可启用/禁用F12和开发者工具
- 调试模式状态保存在localStorage,页面刷新后保持
- 同时控制主应用(app.html)和分享页面(share.html)的调试权限

## 技术实现
1. app.js新增debugMode配置和toggleDebugMode方法
2. app.html添加调试模式开关UI,并修改防调试代码支持debugMode控制
3. share.html添加防调试代码,受localStorage中的debugMode控制

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 16:04:17 +08:00
024e807f75 fix: 优化时间显示逻辑,支持分钟和小时级别的到期提醒
问题: 0.01天(约14分钟)显示为"今天过期",不够精确
原因: 使用Math.ceil向上取整,导致小于1天的时间都显示为1天

修复内容:
1. 改用Math.floor向下取整,更准确反映剩余时间
2. 新增diffMinutes和diffHours变量,支持分钟和小时级别显示
3. 优化判断逻辑:
   - 0-59分钟: 显示"X分钟后过期"
   - 1-23小时: 显示"X小时后过期"
   - 1天: 显示"明天过期"
   - 2-7天: 显示"X天后过期"
   - 7天以上: 显示具体日期时间

修改文件:
- frontend/app.js: formatExpireTime方法(第1317-1335行)
- frontend/share.html: formatExpireTime方法(第836-854行)

测试示例:
- 0.01天(14分钟) → "14分钟后过期 (2025-11-14 12:27)"
- 0.5天(12小时) → "12小时后过期 (2025-11-15 00:00)"
- 1天 → "明天过期 (2025-11-15 12:13)"
- 7天 → "7天后过期 (2025-11-21 12:13)"

关于过期文件清理:
已分析当前机制,过期分享无法访问但记录不会自动删除。
详细分析和解决方案见《分享过期处理机制分析报告.md》。
当前实现是安全的,自动清理功能可作为后续优化。

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 15:22:19 +08:00
84e9a19f3e fix: 修复分享到期时间显示的两个问题
问题1: 分享成功提示中到期时间显示为"永久有效"
- 修复: backend/database.js 的create方法添加返回expires_at字段
- 修复: backend/server.js 的API响应中添加expires_at字段
- 现在创建分享后会正确显示设置的到期时间

问题2: share.html分享页面不显示到期时间
- 新增: 在分享信息中添加到期时间显示(frontend/share.html:527-528)
- 新增: 添加formatExpireTime/isExpiringSoon/isExpired方法
- 效果: 访问分享页面时可以看到"到期时间"或"永久有效"

改进:
- 使用颜色区分状态(绿色=永久/正常, 黄色=即将过期, 红色=已过期)
- 友好的时间显示格式(X天后过期/明天过期等)

注意: 关于0.01天显示问题的优化方案已文档化,需要手动修改app.js

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 13:54:38 +08:00
692b495005 feat: 添加分享到期时间显示功能
新增功能:
- 在分享列表表格中添加"到期时间"列,清晰显示每个分享的有效期
- 在分享创建成功后显示到期时间信息
- 添加友好的时间格式化显示(永久有效/今天过期/明天过期/X天后过期)
- 使用颜色区分不同状态:
  * 绿色: 永久有效
  * 蓝色: 正常有效期
  * 黄色: 即将过期(3天内)
  * 红色: 已过期

技术实现:
- frontend/app.html: 添加到期时间显示UI(表格列+分享结果)
- frontend/app.js: 添加3个辅助方法
  * formatExpireTime(): 格式化到期时间显示
  * isExpiringSoon(): 判断是否即将过期(3天内)
  * isExpired(): 判断是否已过期

改进用户体验:
- 用户可以直观看到分享何时过期
- 即将过期的分享会有醒目的黄色提醒
- 鼠标悬停显示完整的ISO时间戳
- 时间显示本地化,使用中文格式

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 12:23:41 +08:00
70b03c3c6b fix: 修复分享页面文件名过长导致布局溢出的问题
修改内容:
1. 单文件显示 (.single-file-name):
   - 添加 max-width: 100% 限制最大宽度
   - 使用 -webkit-line-clamp: 3 限制最多显示3行
   - 超出部分显示省略号 (...)
   - 改用 word-break: break-word 更优雅的换行

2. 列表视图文件名:
   - 添加 .file-name-container 和 .file-name-text 类
   - 使用 overflow: hidden 和 text-overflow: ellipsis
   - 单行显示,超出显示省略号
   - 设置 min-width: 0 确保flex容器正确缩小

修复效果:
- 文件名再长也不会溢出到界面外
- 单文件视图最多显示3行
- 列表视图单行显示带省略号
- 鼠标悬停在网格视图文件名上会显示完整文件名(title属性)
2025-11-14 09:20:13 +08:00
cd79496fc4 fix: 修复分享页面时间显示问题,正确显示本地时间
- 修改 share.html 中的 formatDate 函数
- 与 app.js 保持一致的 UTC 时间处理逻辑
- 使用 toLocaleString 格式化为本地时间
- 修复分享页面显示 13号(UTC) 而不是 14号(CST) 的问题
2025-11-14 01:08:47 +08:00
61344756e9 fix: 修复前端时间显示问题,正确处理UTC时间并转换为本地时间(北京时间)
- 修改 formatDate 函数,识别 SQLite 返回的 UTC 时间格式
- 自动将 UTC 时间字符串转换为 ISO 格式并添加 'Z' 标记
- JavaScript Date 对象会自动将 UTC 时间转换为本地时间显示
- 修复之前显示 13号(UTC) 而不是 14号(CST) 的问题
2025-11-14 00:51:39 +08:00
927eab2102 test: 添加分享安全性测试脚本
功能:
- 测试分享过期时间检查
- 测试分享密码防爆破保护(list接口)
- 提供手动测试指引

使用方法:
  ./test_share_security.sh
2025-11-14 00:16:05 +08:00
4879d4891f fix: 修复分享过期时间和防爆破保护覆盖不全的安全问题
问题1 - 分享过期时间未强制校验:
- 在ShareDB.findByCode()中添加过期时间检查
- SQL条件: AND (s.expires_at IS NULL OR s.expires_at > datetime('now'))
- 现在过期的分享链接将返回404,无法访问

问题2 - 分享密码防爆破保护覆盖不全:
- 给/api/share/:code/list添加shareRateLimitMiddleware
- 给/api/share/:code/download-file添加shareRateLimitMiddleware
- 在两个接口的密码验证失败时调用recordFailure
- 在两个接口的密码验证成功时调用recordSuccess
- 防止攻击者绕过/verify接口直接暴力破解

影响:
- 分享过期后将无法访问(安全性提升)
- 所有分享密码验证接口都受到限流保护(10次/10分钟)
- 修复了可绕过防爆破保护的安全漏洞
2025-11-14 00:15:15 +08:00
53be6dc145 test: 添加防爆破保护测试脚本
使用方法:
  ./test_rate_limit.sh

功能:
- 自动测试登录防爆破保护
- 连续5次错误登录
- 第6次应返回封锁提示
2025-11-13 23:22:11 +08:00
f6e88d85e7 fix: 修复防爆破保护不生效的问题
问题原因:
- 登录接口缺少recordFailure调用
- 分享密码接口缺少recordFailure和recordSuccess调用

修复内容:
- 在用户不存在时记录失败尝试
- 在密码错误时记录失败尝试
- 在分享密码错误时记录失败尝试
- 在分享密码验证成功时清除失败记录

测试方法:
- 连续5次错误登录后应被封锁30分钟
- 连续10次错误分享密码后应被封锁20分钟
2025-11-13 23:20:25 +08:00
b7ecfa4dff docs: 添加 v1.1.0 详细更新文档 2025-11-13 23:14:40 +08:00