含 app/server/server.cjs 服务端、app/www 网页(admin/auth/项目云/库备份/settings)、 app/ui 图标、cmd 安装脚本、config、wizard、manifest、图标与对接文档。 按仓库规则排除构建产物 *.fpk 与 .mimosa 缓存。
152 lines
7.3 KiB
Plaintext
Executable File
152 lines
7.3 KiB
Plaintext
Executable File
══════════════════════════════════════════════════════════
|
||
项目云「删除接口」客户端对接文档
|
||
2026-09-24 · 适用服务端 v1.5.1
|
||
══════════════════════════════════════════════════════════
|
||
|
||
一、接口总览
|
||
──────────────────────────────
|
||
删除接口是项目云 API 之一,与其他项目云接口共用同一套
|
||
鉴权方式(手机号 + 密码)。全部项目云接口:
|
||
|
||
POST /api/proj/upload 上传项目 zip(覆盖式,≤2GB,每会员共 1GB)
|
||
GET /api/proj/list 列出该手机号名下全部项目
|
||
GET /api/proj/download 下载项目 zip
|
||
POST /api/proj/delete ★ 本文档:删除一个项目
|
||
|
||
项目云所有接口都有两种调用方式:
|
||
· 方式 A:信封加密通道(推荐,与登录/注册同一套封装)
|
||
· 方式 B:HTTPS 明文 JSON(与上传/下载同一套封装)
|
||
|
||
二、服务端实现说明(方式 B:HTTPS 明文)
|
||
──────────────────────────────
|
||
【请求】
|
||
POST https://服务器IP:端口/api/proj/delete
|
||
Content-Type: application/json
|
||
|
||
请求体(JSON,UTF-8):
|
||
{
|
||
"手机号": "13800001111",
|
||
"密码": "该会员的登录密码",
|
||
"编号": "要删除的项目编号"
|
||
}
|
||
|
||
【服务端处理流程】
|
||
1. 校验手机号+密码与 huiyuan.json 中会员记录匹配
|
||
(不匹配 → {ok:false, msg:"手机号或密码错误"})
|
||
2. 编号经文件名安全化后拼出项目目录,并做防路径穿越校验
|
||
(拼接结果必须仍在 项目云 根目录之下)
|
||
3. 直接递归删除该项目的整个目录(项目.zip + meta.json)
|
||
4. 删除是不可恢复的物理删除
|
||
|
||
【响应】
|
||
成功: {"ok": true}
|
||
失败: {"ok": false, "msg": "失败原因"}
|
||
常见失败:
|
||
"手机号或密码错误" 鉴权失败
|
||
"参数错误" 手机号或编号缺失
|
||
"该接口已迁移至加密通道,请升级客户端并使用 https://IP:端口 连接"
|
||
用了 http:// (必须 https)
|
||
|
||
三、服务端实现说明(方式 A:信封加密通道 /api/enc)
|
||
──────────────────────────────
|
||
删除接口与项目列表一起,同时注册在加密通道内
|
||
(ENC_ROUTES),客户端如果已经在用登录/注册的信封封装,
|
||
删除不需要单独再发明文请求,走同一封装即可。
|
||
|
||
【流程】
|
||
1. GET https://服务器IP:端口/api/pubkey
|
||
→ {"ok":true, "pubkey":"RSA公钥PEM", "keyfp":"指纹"}
|
||
2. 客户端随机生成 32 字节 AES-256 密钥 + 16 字节 IV
|
||
3. 业务 JSON(下述 inner)用 AES-256-CBC 加密
|
||
4. AES 密钥用 RSA-2048 OAEP(SHA-1) 封装
|
||
5. POST /api/enc,请求体:
|
||
{
|
||
"k": AES密钥的RSA-OAEP封装(base64),
|
||
"iv": AES IV(hex),
|
||
"data": 密文(base64),
|
||
"mac": HMAC-SHA256(ts+'.'+nonce+'.'+iv+'.'+data) hex,
|
||
"ts": 毫秒时间戳(±5分钟有效),
|
||
"nonce":随机数(10分钟内不可重复)
|
||
}
|
||
其中密文解开后是 inner:
|
||
{ "path": "/api/proj/delete",
|
||
"body": { "手机号":"...", "密码":"...", "编号":"..." } }
|
||
6. 响应也是加密的:{"ok":true,"iv":..,"mac":..,"data":..}
|
||
data 用同一 AES 密钥解开即 {"ok":true}
|
||
|
||
【注意】
|
||
· /api/enc 只在 HTTPS 端口提供,http 端口一律返回
|
||
TLS_REQUIRED 迁移提示
|
||
· 防重放:同一 nonce 10 分钟内第二次提交会被拒绝
|
||
· HMAC 校验失败 = 数据被篡改,服务端直接拒绝
|
||
|
||
四、端口与地址
|
||
──────────────────────────────
|
||
· 客户端所有接口一律走 HTTPS:
|
||
https://飞牛主机IP:HTTPS端口
|
||
· HTTPS 端口 = 网页端口 + 1(默认网页 12701 → HTTPS 12702)
|
||
· 证书是自签的,客户端需忽略证书校验
|
||
(.NET: ServicePointManager.ServerCertificateValidationCallback
|
||
返回 true;或比对 /api/pubkey 的 keyfp 指纹)
|
||
· 手机号 11 位数字;密码即会员登录密码(与 /api/login 相同)
|
||
|
||
五、调用时序建议
|
||
──────────────────────────────
|
||
1. (首次)GET /api/pubkey 取公钥与指纹,指纹可展示给
|
||
用户核对,防中间人
|
||
2. 客户端本地登录缓存手机号+密码(或调用 /api/login 验证)
|
||
3. GET /api/proj/list 拿项目编号列表(编号即删除参数)
|
||
4. 用户确认要删除后,POST /api/proj/delete 传编号
|
||
5. 依返回 ok 刷新本地项目列表
|
||
|
||
六、删除的边界行为
|
||
──────────────────────────────
|
||
· 删除的单位是"项目编号":一个编号对应项目云里一个
|
||
目录(项目.zip + meta.json),整体删除
|
||
· 编号不存在时不会报错,同样返回 {ok:true}(幂等)
|
||
· 不提供批量删除参数,多个项目由客户端循环逐条调用
|
||
(每条之间建议留 200ms 间隔,避免触发限速)
|
||
· 登录/管理接口按 IP 限速(1 分钟内失败≥10 次锁 60 秒),
|
||
删除接口的鉴权失败不计入限速计数,无请求频率限制
|
||
|
||
七、明文调用示例(方式 B,C#)
|
||
──────────────────────────────
|
||
// 忽略自签证书
|
||
ServicePointManager.ServerCertificateValidationCallback =
|
||
(s, cert, chain, err) => true;
|
||
|
||
var url = "https://192.168.1.10:12702/api/proj/delete";
|
||
var body = "{\"手机号\":\"13800001111\",\"密码\":\"123456\",\"编号\":\"XM20260924001\"}";
|
||
var req = (HttpWebRequest)WebRequest.Create(url);
|
||
req.Method = "POST";
|
||
req.ContentType = "application/json";
|
||
var bytes = Encoding.UTF8.GetBytes(body);
|
||
using (var st = req.GetRequestStream()) st.Write(bytes, 0, bytes.Length);
|
||
try {
|
||
using (var resp = (HttpWebResponse)req.GetResponse())
|
||
using (var rs = new StreamReader(resp.GetResponseStream(), Encoding.UTF8)) {
|
||
Console.WriteLine(rs.ReadToEnd());
|
||
// 成功输出: {"ok":true}
|
||
}
|
||
} catch (WebException ex) {
|
||
using (var rs = new StreamReader(ex.Response.GetResponseStream(), Encoding.UTF8))
|
||
Console.WriteLine(rs.ReadToEnd()); // {"ok":false,"msg":"..."}
|
||
}
|
||
|
||
八、错误码速查
|
||
──────────────────────────────
|
||
{"ok":true} 删除成功(含"项目本来就不存在")
|
||
手机号或密码错误 鉴权失败
|
||
参数错误 手机号或编号为空
|
||
TLS_REQUIRED / 该接口已迁移… 用了 http,改 https
|
||
时间戳超出允许窗口(±5分钟) 信封模式 ts 偏差过大,校时
|
||
重复的请求(疑似抓包重放) 信封模式 nonce 重复
|
||
|
||
九、与原「客户端对接示例.cs」的关系
|
||
──────────────────────────────
|
||
原示例文件(项目根目录 客户端对接示例.cs)覆盖登录/注册/
|
||
信封加密的完整实现。本文档只补充"删除"这一个接口:
|
||
两种调用方式与列表/上传/下载完全同构,把示例中已有的
|
||
信封 path 换成 /api/proj/delete、body 换成
|
||
{手机号,密码,编号} 即可,无任何新协议。
|