Files
ctbjrj/会员服务器
dqb-dev 65755bf520 会员服务器:上传肥牛应用源码 v1.5.1(fnnas.huiyuan 完整 fpk 工程结构)
含 app/server/server.cjs 服务端、app/www 网页(admin/auth/项目云/库备份/settings)、
app/ui 图标、cmd 安装脚本、config、wizard、manifest、图标与对接文档。
按仓库规则排除构建产物 *.fpk 与 .mimosa 缓存。
2026-10-02 00:03:20 +08:00
..

fnnas.huiyuan 会员服务器(飞牛 fnOS 应用)

成套报价软件的会员系统服务器,打包为飞牛 fnOS 原生应用(.fpk)。v1.4.0 起全站强制 HTTPS(自签证书)+ 应用层信封加密。

  • 产物:fnnas.huiyuan_1.4.0_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 按会员查看/下载/删除云上项目
库备份管理页 /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 权限文件)。
  • 已知边界:传输为 HTTP(密码在局域网传输中可见,客户端限制;哈希解决的是数据库文件泄露问题);限速/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)

打包

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 不支持原地升级)

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
# 卸载会回收目录授权;数据目录在应用目录外不受影响

本地测试(模拟飞牛环境)

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/项目云)路径规则不同