4.1 KiB
4.1 KiB
自定义菜单安全嵌入部署
背景
用户需要在 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 当前配置:
[
{
"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的 CSPframe-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。