Files
dqb-dev c1849f97d5 会员服务器:文档补齐 v1.5.1(README 版本/功能更新,补缺失的 CHANGELOG v1.5.1 条目)
README:产物名 1.4.0→1.5.1;开头补当前版本说明与 1.5.0/1.5.1 特性;
项目云管理页补「删除选中」批量删除(1.5.1 新增,此前未记录);
修正过期的「已知边界:传输为 HTTP」(1.4.0 起已全站 HTTPS,仅剩自签证书告警边界)。
CHANGELOG:补写缺失的 v1.5.1 条目(此前最高只到 v1.5.0)。
新增首次上传时因 root 000 权限漏掉的 客户端对接示例.cs;
示例注释中的真实手机号/密码替换为占位符(仓库公开可读)。
2026-10-02 00:31:27 +08:00

147 lines
9.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# fnnas.huiyuan 会员服务器(飞牛 fnOS 应用)
成套报价软件的会员系统服务器,打包为飞牛 fnOS 原生应用(.fpk)。v1.4.0 起全站强制 HTTPS(自签证书)+ 应用层信封加密;当前版本 v1.5.1(v1.5.0 起支持导入正规 SSL 证书,v1.5.1 新增项目云批量删除)。
- **产物**:`fnnas.huiyuan_1.5.1_all.fpk`
- **默认端口**:12701(安装向导可改)
- **运行时**:飞牛自带 Node.js(`install_dep_apps=nodejs_v22`),零第三方依赖
- **源码来源**:`/vol2/1000/fnosyy/会员服务器/`(server.cjs 改造 + www 页面移植)
## 功能
| 功能 | 说明 |
|---|---|
| 客户端 API | 凭据类(登录/注册/查会员/改密)走 /api/enc 信封加密;项目云走 TLS 直连;业务字段与原版一致 |
| 项目云 API | `/api/proj/upload`(JSON头+空行+zip 二进制,覆盖式,上限 2GB)、`/api/proj/list`、`/api/proj/download`、`/api/proj/delete`;上传校验会员、文件名安全化、防路径穿越 |
| 会员管理页 | `http://NAS_IP:端口/`(admin.html) |
| 项目云管理页 | `/xiangmu-cloud.html` 按会员查看/下载/删除云上项目;v1.5.1 起支持勾选后**删除选中**(表头复选框全选,逐条调用 `/api/proj/delete`,完成后显示成功/失败计数并刷新列表) |
| 库备份管理页 | `/lib-cloud.html` 只显示 LIB_ 前缀条目(方案库/用户库/柜体库/铜排铝排库/企业信息) |
| 管理登录 | 四页面需管理密码登录(安装向导设置),设置页可改密码/关闭注册 |
| 设置页 | `/settings.html` 显示端口/版本/会员数/数据库文件/项目云目录,切换数据目录(连库+项目云一起迁移) |
| 安装向导 | 端口(默认 12701)+ 数据目录(可选,留空=默认)+ 管理密码(必填 ≥6 位) |
| 全站加密 | 唯一 HTTPS 端口;TLS 自签证书自动生成;信封加密(RSA+AES+HMAC+防重放);证书可在设置页下载 |
| 装后改端口 | 应用中心 → 会员服务器 → 应用设置(留空=不修改) |
| 目录授权 | 应用设置 → 目录授权,或设置页"授权新目录"按钮(管理员,需 fnOS ≥ 1.2.0401) |
## 客户端接口(v1.2.0 起项目云需带密码——客户端必须同步升级)
| 接口 | 客户端改动 |
|---|---|
| `POST /api/login` | 不变 |
| `POST /api/register` | 不变(服务端校验 11 位手机号、密码 4-64 位) |
| `GET /api/member` | 不变 |
| `POST /api/changepwd` | 不变 |
| `POST /api/proj/upload` | JSON 头新增 `"密码": "该会员密码"` |
| `GET /api/proj/list` | URL 新增 `&密码=<该会员密码>`(URL 编码) |
| `GET /api/proj/download` | 同上 |
| `POST /api/proj/delete` | body 新增 `"密码": "该会员密码"` |
不带上传/查询密码的项目云请求会返回 `{ok:false, msg:"手机号或密码错误"}`。
## 全站 HTTPS 与双层加密(v1.4.0)
**全站只有一个 HTTPS 端口**(默认 12701,安装向导可改),HTTP 明文通道已彻底停用——浏览器打开 `http://IP:端口` 无法连接,必须使用 `https://IP:端口`。
- 自签证书首次启动自动生成(OpenSSL,存应用配置目录);设置页可查看 TLS 证书指纹 / RSA 公钥指纹并**下载证书**(安装到 Windows"受信任的根证书颁发机构"后浏览器不再警告)
- 安全响应头:HSTS(max-age 1 年)、nosniff、X-Frame-Options
- TLS 初始化失败服务拒绝启动(强制 HTTPS 是硬性要求)
### 第 2 层:应用层信封加密(客户端凭据类通讯)
即使 TLS 被绕过(如中间人持自签证书),业务数据仍是密文:
```
① GET /api/pubkey (HTTPS) → 服务器 RSA-2048 公钥 + 公钥指纹
② 每次请求(登录/注册/查会员/改密/项目云列表/删除):
aesKey = 随机32字节; iv = 随机16字节; nonce = 随机16字节hex; ts = 毫秒时间戳
data = BASE64( AES-256-CBC(iv, {"path":"/api/login","body":{...业务参数}}) )
k = BASE64( RSA-OAEP-SHA1(公钥, aesKey) ) ← 私钥解,永不出服务器
mac = HEX( HMAC-SHA256(aesKey, ts+"."+nonce+"."+iv+"."+data) )
POST /api/enc {"k","iv","ts","nonce","mac","data"}
③ 服务器:RSA解封→AES解密→验签→时间戳±5分钟+nonce防重放→内部路由→同信封格式加密响应
④ 客户端验签解密响应
```
- 项目 zip 上传/下载走 TLS 直连(大文件不做信封,`密码` 参数照旧)
- 管理页(admin/xiangmu/lib/settings)在 HTTPS 下照常使用管理密码登录
### 客户端改动清单(C# 参考实现见项目内 `客户端对接示例.cs`)
1. 地址改为 `https://NAS_IP:12701`;信任自签证书(回调跳过或安装证书)
2. 旧 .NET 启用 TLS1.2:`ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072`
3. 登录/注册/查会员/改密/项目云列表/删除 → 走 `EncryptedCall(path, json)` 信封封装
4. 项目上传/下载 → 走 TLS 直连(同 v1.2.0 加 `密码` 参数的方式)
5. 业务字段与响应格式与之前完全一致
### 信封错误响应(明文返回,便于客户端提示)
| 场景 | 响应 |
|---|---|
| 时间戳超出 ±5 分钟 | `{"ok":false,"msg":"时间戳超出允许窗口(±5分钟)"}` |
| 重放同一 nonce | `{"ok":false,"msg":"重复的请求(疑似抓包重放),已拒绝"}` |
| 密文/HMAC 被篡改 | `{"ok":false,"msg":"签名校验失败(数据可能被篡改)"}` |
| 信封字段缺失/损坏 | `{"ok":false,"msg":"信封字段缺失"}` 等 |
## 安全模型(v1.4.0)
- **管理密码**:安装向导必填(sha256+盐存 app.env),登录管理页面与保护 `/api/list`、`/api/save`、`/api/settings`、`/api/admin/changepwd`;token 24h 过期;修改管理密码在设置页"安全"卡片。忘记密码:应用设置(config 向导)重新设置,或重装时在 env 里传 `wizard_admin_pwd`。
- **会员密码哈希存储**(v1.3.0,客户端零改动):存 `盐(32hex)$sha256(64hex)`,每会员独立盐;服务启动自动把存量明文升级为哈希(先备份,成功后用哈希版刷新 .bak)。管理页密码列不显示密码——输入新值即重置,留空保持不变。`/api/save` 密码语义:空=保持、明文=重置、哈希格式=原样。
- **项目云鉴权**:会员密码或管理 token 二选一。
- **限速**:登录/注册/管理登录失败按 IP 限速(1 分钟 10 次锁 60 秒,重启清零)。
- **注册开关**:设置页可关闭开放注册(`HY_REG_OPEN`)。
- **配额与备份**:每会员项目云 1GB;整表保存/迁移前自动 `huiyuan.json.bak`(tmp+rename 原子写,兼容飞牛 ACL 000 权限文件)。
- 已知边界:TLS 证书为自签时浏览器会告警(可在设置页下载证书安装到"受信任的根证书颁发机构";v1.5.0 起也可导入正规证书);限速/token 在内存(重启清零)。
## 数据目录解析顺序(数据库 huiyuan.json 与 项目云/ 都在这里)
1. `HY_DB_DIR`(向导指定 / 设置页切换,写入 `TRIM_PKGETC/app.env`)
2. `TRIM_DATA_SHARE_PATHS`(应用数据目录:文件管理 → 应用文件 → fnnas.huiyuan/数据目录)
3. `TRIM_PKGVAR/files`
目录不可写自动降级到下一级;设置页显示实际生效路径。切换目录时自动迁移 `huiyuan.json` + `项目云/`。
## 目录结构
```
fnnas.huiyuan/
├── manifest # service_port=12701, install_dep_apps=nodejs_v22, micro_app=true
├── wizard/install|config # 安装向导 / 装后配置向导(wizard_port、wizard_dbdir)
├── app/server/server.cjs # 主服务(纯 Node http,含项目云 API);首次启动自动建空会员库
├── app/www/ # admin + xiangmu-cloud + lib-cloud + settings + sdk/
├── app/ui/config # 桌面入口,port 用 ${wizard_port} 占位符
├── cmd/ # main(start/stop/status) + install/config 回调(写 app.env)
└── config/ # privilege(run-as package) + resource(data-share + api-scope)
```
## 打包
```bash
cd /vol2/1000/fnosyy
.agents/skills/fnos-fpk-packaging/fnpack-1.2.3-linux-amd64 build -d fnnas.huiyuan
# 注意:打包前确认 app/ 内文件权限位正常(644),源目录复制来的文件可能是 000
```
## NAS 升级流程(install-fpk 不支持原地升级)
```bash
printf 'wizard_port=12701\nwizard_dbdir=/vol2/1000/成套报价软件数据库\n' > /tmp/hy-env
appcenter-cli stop fnnas.huiyuan && appcenter-cli uninstall fnnas.huiyuan
appcenter-cli install-fpk fnnas.huiyuan_X.Y.Z_all.fpk -e /tmp/hy-env
appcenter-cli start fnnas.huiyuan
# 卸载会回收目录授权;数据目录在应用目录外不受影响
```
## 本地测试(模拟飞牛环境)
```bash
HY_PORT=18701 TRIM_PKGETC=/tmp/etc TRIM_PKGVAR=/tmp/var \
TRIM_DATA_SHARE_PATHS=/tmp/share node app/server/server.cjs
```
## 注意
- 客户端(Windows 成套报价软件)连接地址需改为 `飞牛主机IP:端口`(原为 127.0.0.1:12701)
- 项目云接口自 v1.2.0 起需带会员密码(见上方对照表);登录/注册/查会员/改密协议始终不变
- 开放 API(目录授权查询)在非飞牛环境会优雅降级,不影响其他功能
- 项目云存储在数据目录(DB_DIR/项目云),与源码 Windows 版(ROOT/项目云)路径规则不同