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

4.1 KiB
Raw Blame History

自定义菜单安全嵌入部署

背景

用户需要在 Sub2API 用户侧增加一级菜单,让用户点击后在站内看到第三方商铺页:

  • 菜单名称:购买套餐
  • 页面地址:https://pay.ldxp.cn/shop/5HAP5JVN
  • 入口路径:/custom/shop

核心安全边界是第三方 iframe 不应收到 Sub2API 的用户 ID、登录 token 或来源 URL。

本次实现

  • custom_menu_items 增加三态字段 omit_auth_context
    • true:安全嵌入,不追加 user_idtokensrc_hostsrc_url
    • false:允许追加认证上下文,但只允许部署配置或环境变量声明的受信 origin。
    • 缺省兼容旧菜单public/injection 输出时如果 URL 不受信,会收敛为 true
  • 新增菜单默认安全嵌入,后台 UI 增加“安全嵌入第三方页面”开关。
  • 受信根只来自 cfg.Server.FrontendURLCUSTOM_MENU_AUTH_CONTEXT_TRUSTED_ORIGINS,数据库/后台设置里的 frontend_url 不作为自授权信任根。
  • 用户进入 /custom/:id 时强制刷新 public settings降低信任策略撤销后的旧缓存风险。
  • admin-only 自定义页面 fail closed即使来自 admin settings也不向 iframe 传 token。
  • 侧边栏左上角不再渲染版本号。

线上部署

  • 服务器:个人-US-racknerd-0526-3c4g
  • IP216.45.59.243
  • 部署目录:/opt/sub2api
  • 当前镜像:sub2api:custom-menu-safe-embed-20260527-r2
  • 当前镜像 IDsha256:ceeea1a913ea8386f24b4296b856295c18febd0b19eeb1e92de4ef9512e3f3a2
  • 当前提交:7954492cee99
  • 当前版本:0.1.131
  • 上一版镜像:sub2api:custom-menu-safe-embed-20260527
  • 镜像 IDsha256: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 SHA256321b69bcf40470be9f2de10f8f1114ebd6bd7e6e014783b123c7160781ac127d
  • r2 runtime patch/tmp/sub2api-custom-menu-safe-embed-r2-runtime-patch.tar.gz
  • r2 runtime patch SHA256962de880c5e0917e3c6b351fd1955c3d94c8f7b6fcfae558492535c08faac0d0
  • 部署前备份:/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 当前配置:

[
  {
    "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 不应包含 tokenuser_idsrc_hostsrc_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/.envSUB2API_IMAGE 回退到部署前镜像,再执行 docker compose up -d sub2api