sub2api/docs/memorys/2026-05-27-自定义菜单安全嵌入部署.md

81 lines
4.1 KiB
Markdown
Raw 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.

# 自定义菜单安全嵌入部署
## 背景
用户需要在 Sub2API 用户侧增加一级菜单,让用户点击后在站内看到第三方商铺页:
- 菜单名称:`购买套餐`
- 页面地址:`https://pay.ldxp.cn/shop/5HAP5JVN`
- 入口路径:`/custom/shop`
核心安全边界是第三方 iframe 不应收到 Sub2API 的用户 ID、登录 token 或来源 URL。
## 本次实现
- `custom_menu_items` 增加三态字段 `omit_auth_context`
- `true`:安全嵌入,不追加 `user_id``token``src_host``src_url`
- `false`:允许追加认证上下文,但只允许部署配置或环境变量声明的受信 origin。
- 缺省兼容旧菜单public/injection 输出时如果 URL 不受信,会收敛为 `true`
- 新增菜单默认安全嵌入,后台 UI 增加“安全嵌入第三方页面”开关。
- 受信根只来自 `cfg.Server.FrontendURL``CUSTOM_MENU_AUTH_CONTEXT_TRUSTED_ORIGINS`,数据库/后台设置里的 `frontend_url` 不作为自授权信任根。
- 用户进入 `/custom/:id` 时强制刷新 public settings降低信任策略撤销后的旧缓存风险。
- admin-only 自定义页面 fail closed即使来自 admin settings也不向 iframe 传 token。
- 侧边栏左上角不再渲染版本号。
## 线上部署
- 服务器:`个人-US-racknerd-0526-3c4g`
- IP`216.45.59.243`
- 部署目录:`/opt/sub2api`
- 当前镜像:`sub2api:custom-menu-safe-embed-20260527-r2`
- 当前镜像 ID`sha256:ceeea1a913ea8386f24b4296b856295c18febd0b19eeb1e92de4ef9512e3f3a2`
- 当前提交:`7954492cee99`
- 当前版本:`0.1.131`
- 上一版镜像:`sub2api:custom-menu-safe-embed-20260527`
- 镜像 ID`sha256:356653e0e5a7b688faacb728a0f94d450e102393fd73bb16c705000f359133de`
- 部署方式:本地构建 linux/amd64 Go 二进制并嵌入前端,上传 runtime patch tar 到远程,在远程基于 `weishaw/sub2api:latest` 替换二进制和资源后 `docker commit` 生成本地镜像。
- runtime patch`/tmp/sub2api-custom-menu-runtime-patch-20260527.tar.gz`
- runtime patch SHA256`321b69bcf40470be9f2de10f8f1114ebd6bd7e6e014783b123c7160781ac127d`
- r2 runtime patch`/tmp/sub2api-custom-menu-safe-embed-r2-runtime-patch.tar.gz`
- r2 runtime patch SHA256`962de880c5e0917e3c6b351fd1955c3d94c8f7b6fcfae558492535c08faac0d0`
- 部署前备份:`/opt/sub2api/backups/deploy-custom-menu-20260526-222849`
- r2 部署前备份:`/opt/sub2api/backups/deploy-custom-menu-r2-20260527-000642`
- 菜单配置备份:`/opt/sub2api/backups/custom-menu-shop-20260526-224153`
## 线上菜单配置
远程 PostgreSQL `settings.custom_menu_items` 当前配置:
```json
[
{
"id": "shop",
"label": "购买套餐",
"icon_svg": "",
"url": "https://pay.ldxp.cn/shop/5HAP5JVN",
"visibility": "user",
"sort_order": 0,
"omit_auth_context": true
}
]
```
直接改数据库后需要重启 `sub2api` 容器或通过应用设置接口触发缓存刷新,否则 CSP 动态 `frame-src` 可能暂时不包含新 iframe origin。
## 验证记录
- `https://catproxy.lilifamily.com/api/v1/settings/public` 返回 `shop` 菜单项。
- `https://proxy.api.lilifamily.com/api/v1/settings/public` 返回 `shop` 菜单项。
- `https://catproxy.lilifamily.com/custom/shop` 返回 `200`
- `https://proxy.api.lilifamily.com/custom/shop` 返回 `200`,响应头含 `X-Proxy-Ng-Node: jppro-akile-0504-1c1g`
- `/custom/shop` 的 CSP `frame-src` 已包含 `https://pay.ldxp.cn`
- `omit_auth_context=true` 时 iframe URL 不应包含 `token``user_id``src_host``src_url`
- r2 远程二进制核对:`Sub2API 0.1.131 (commit: 7954492cee99, built: 2026-05-27T07:02:24Z)`
- r2 公网 settings 核对:`proxy.api.lilifamily.com/api/v1/settings/public` 返回 `version=0.1.131``购买套餐``omit_auth_context=true`
- r2 UI 变更:侧边栏左上角不再渲染版本号。
## 回滚
- 删除或清空 `settings.custom_menu_items` 中的 `shop` 项,并重启 `sub2api` 容器刷新 CSP 缓存。
- 或把 `/opt/sub2api/.env``SUB2API_IMAGE` 回退到部署前镜像,再执行 `docker compose up -d sub2api`