4.5 KiB
4.5 KiB
davbox · 需求文档
0. 定位
用户需要一个概念只有两个的自建 WebDAV 服务:
- admin:管理账号(新增 / 删除 / 改密码 / 看目录与用量)
- client:账号登录后管理自己的文件
- 主要消费者是 App:思源笔记、Joplin 等通过 WebDAV 同步
设计分工(关键):WebDAV 协议不自研(底盘用 Go 官方 golang.org/x/net/webdav),
产品层 100% 自研(账号模型、目录隔离、admin 页、client 页)。
1. 阶段一:底盘(本次委托范围)
做:一个 Go 二进制,读账号配置,按账号隔离地提供完整 WebDAV 服务。 不做(留给阶段二/三):admin 页、client 页、配额、HTTPS、SSO、日志文件、数据库。
阶段一唯一目的:证明底盘与隔离是可信的。
硬性边界(违反任何一条即视为任务失败)
- 绝不 执行
systemctl/service任何操作 - 绝不 执行
pkill/killall/kill任何已存在的进程 - 绝不 触碰任何已在运行的端口(80 / 443 等)
- 绝不 修改仓库之外的任何系统配置(服务、容器、nginx、cron、其他项目的文件)
- 不新增第三方依赖:只允许
golang.org/x/net/webdav - 只准修改本仓库内的文件
- 服务只准监听
127.0.0.1:18900 - 测试进程自己起自己收,按 PID 收尾
交付物
./
├── cmd/davbox/main.go # 入口
├── internal/account/ # 账号加载 + Basic 认证 + 路由
├── internal/fs/ # 按账号 chroot 的文件系统封装
├── go.mod # module davbox
├── accounts.json # 示例:app1 / app2
└── davbox # go build 产物
功能要求
- 配置:
accounts.json为数组,每项{ "user": "app1", "pass": "...", "root": "/abs/path", "readonly": false } - 认证:HTTP Basic,口令用
crypto/subtle常量时间比较; 未认证/失败 →401,必须带WWW-Authenticate: Basic realm="davbox"(客户端靠它重试) - URL 空间:
/<user>/...→ 剥离前缀映射到该账号root下的相对路径 例:账号app1(root=/srv/dav/app1)收PUT /app1/notes/a.txt→ 落盘/srv/dav/app1/notes/a.txt - 越权必须失败:访问他人前缀、
../、%2e%2e、双重编码、绝对路径逃逸 → 401/403/404 之一,绝不允许成功 - 只读账号:PUT / DELETE / MKCOL / MOVE / COPY / PROPPATCH → 403;GET / PROPFIND 正常
- 六个动词可用:GET / PUT / DELETE / MKCOL / MOVE / PROPFIND(PROPFIND 正确处理
Depth: 0与Depth: 1并返回合法207 Multi-Status) - 启动参数:
-addr 127.0.0.1:18900 -c accounts.json;日志到 stdout,不写文件 root不存在时自动MkdirAll- Basic 认证通过后的请求不得把口令写进日志
验收标准(逐条实测,不看自述)
| # | 项目 | 通过条件 |
|---|---|---|
| 1 | 六动词 | GET / PUT / DELETE / MKCOL / MOVE / PROPFIND 全部返回正确状态码 |
| 2 | 跨账号读 | app1 读 app2 目录 → 401/403/404 |
| 3 | 跨账号写 | app1 写 app2 目录 → 401/403/404 |
| 4 | ../ 逃逸 |
错误码,且磁盘不产生越狱文件 |
| 5 | %2e%2e 逃逸 |
同上 |
| 6 | 落盘位置 | app1 写的内容只在 app1 的 root 里 |
| 7 | 未认证 | 401 且响应头含 WWW-Authenticate |
| 8 | 只读账号 | 写 403 / 读 200-207 |
| 9 | 空闲内存 | RSS < 30 MB |
| 10 | 收尾 | 只监听 127.0.0.1:18900;按 PID 可干净停掉 |
| 11 | 合规(加分项) | 若能跑通 litmus 基础集更好(internal/litmus_test_server.go 有现成入口) |
2. 阶段二:admin 页 + client 页(下一轮委托)
- admin 页(登录:独立管理员账号)
- 列表:应用名 / 目录 / 已用空间 / 只读开关 / 最近活动
- 操作:新增应用(自动生成强口令 + 建目录)、改密码、改只读、停用、删除(目录保留)
- 每行一个「复制连接信息」按钮:地址 + 用户名 + 口令,一次复制走
- client 页(登录:应用账号)
- 浏览 / 上传 / 下载 / 删除 / 新建文件夹 / 重命名;面包屑导航;移动端可用(不隐藏导航)
- 视觉:Swiss 极简;文案中文、克制,不放技术说明
3. 阶段三(可选,等你点名)
配额限制、用量趋势、分享链接(走带 token 的公开链接那套口径)、审计日志页