管理后台鉴权架构
当前状态:飞书 SSO、前端失败关闭、服务端默认鉴权均已落地
BeeX 后台由静态管理前端、独立 SSO 服务和各国家独立 admin-service 共同完成鉴权。前端登录守卫只负责体验,真正的安全边界是 admin-service 对业务接口的服务端会话校验。
1. 组件与责任
管理前端
admin.beexofficial.com
保存 session、触发登录、调用 verify,并给所有业务请求附带 Bearer session。
统一 SSO
sso.beexofficial.com
完成飞书 OAuth、Tenant 校验、会话签发与会话验证。
国家 admin-service
admin-api-{country}[-test].beexofficial.com
读取共享 Redis 会话并在服务端拦截管理业务接口。
2. 登录与接口调用时序
浏览器登录、会话签发及业务接口校验
sequenceDiagram
autonumber
actor Operator as 运营人员
participant Admin as 管理前端
participant SSO as beex-sso
participant Feishu as 飞书 OAuth
participant Redis as 共享 Redis
participant API as 国家 admin-service
Operator->>Admin: 打开 admin.beexofficial.com
Admin->>Admin: authGuard 检查 bx_admin_session
alt 没有有效会话
Admin->>SSO: GET /admin/auth/feishu/login?redirect=当前页面
SSO->>Redis: 写入一次性 state(5 分钟)
SSO-->>Operator: 302 到飞书授权页
Operator->>Feishu: 确认授权
Feishu->>SSO: callback(code, state)
SSO->>Feishu: code 换用户身份
SSO->>SSO: 校验 tenant_key 和回跳白名单
SSO->>Redis: 写 bx:prd:session:{sid}
SSO-->>Admin: 回跳并携带 prd_session
end
Admin->>SSO: GET /verify + Bearer sid
SSO->>Redis: 查询会话
SSO-->>Admin: 返回登录人
Admin->>API: /api/v1/** + Bearer sid
API->>Redis: AdminApiAuthInterceptor 校验会话
alt 会话有效
API-->>Admin: 执行业务并记录操作人
else 缺失或过期
API-->>Admin: 401 UNAUTHORIZED
end
3. 前端守卫
| 项目 | 当前实现 |
|---|---|
| 实现位置 | beex-admin-page/console-core.js 的 authGuard |
| SSO 地址 | https://sso.beexofficial.com,不随顶部数据环境切换 |
| 本地会话 | localStorage.bx_admin_session;回跳参数名为 prd_session |
| 失败策略 | 页面先隐藏;verify 返回非 2xx、网络失败或 CORS 异常时清理会话并重新登录,不显示未鉴权页面 |
| 本地预览 | localhost、局域网和 .local 可跳过页面守卫,但不能绕过后端接口鉴权 |
| 操作人 | verify 返回的飞书姓名和 openId 写入本地状态,并随请求用于审计显示 |
4. SSO 会话
| 对象 | 存储与约束 |
|---|---|
| OAuth state | Redis bx:prd:oauth:state:*,一次性读取并删除,TTL 5 分钟 |
| 登录会话 | Redis bx:prd:session:*,默认 TTL 604800 秒(7 天) |
| 组织限制 | 配置 Tenant Key 后,飞书返回的 tenant_key 必须匹配,否则返回 403 |
| 回跳限制 | redirect 必须是 HTTP(S) 绝对地址,且 host 命中 beexofficial.com 白名单 |
| 多环境 | 一套 SSO 给多个管理前端和文档站发证;各国家 admin-service 必须连接能读取同一 session key 的 Redis |
5. 服务端默认拒绝
beex-admin-service 的 AdminApiAuthWebConfig 将 AdminApiAuthInterceptor 注册到服务内所有 /api/v1/**。除显式机器接口外,新增接口天然继承会话校验,无需开发逐个记忆添加注解。
机器接口必须使用自己的凭证H5 包注册、监控回调、CI 图片上传、只读诊断及 App 内文案审校不能依赖浏览器飞书会话,但必须分别使用流水线 token、回调 token、诊断 token、签名或 BeeX 用户白名单。显式排除拦截器不等于匿名开放。
H5 注册 token 不允许留空
POST /api/v1/admin/h5-packages 在配置流水线 token 后才会校验 X-Pipeline-Token。测试与生产环境都必须配置,不能依赖代码中的兼容放行分支。6. 环境切换不是权限
管理前端只有一套,通过顶部环境选择器切换印尼测试、印尼生产、马来测试或马来生产的 admin API。选择器只决定请求地址,不授予权限。每个国家的数据中心和 admin-service 独立部署,并分别执行服务端鉴权。
7. 尚未完成的授权层
当前系统已经解决“是谁”和“是否登录”,但还没有完整解决“这个人能对哪个国家、哪个菜单执行什么动作”。后续 RBAC 至少应包含:
- 角色:超级管理员、运营、财务、客服、风控、只读审计;
- 资源:用户、订单、佣金、提现、活动、配置、H5 发布、平台账号;
- 动作:查看、创建、编辑、审批、发布、回滚、导出;
- 范围:国家、测试/生产环境及必要的数据归属范围;
- 高风险动作:二次确认、强审计,必要时双人复核。
8. 发布检查
| 检查项 | 要求 |
|---|---|
| admin API 鉴权开关 | 生产必须设置 SEAHUB_ADMIN_API_AUTH_ENABLED=true |
| 共享会话 | SSO 和对应 admin-service 能读取相同 bx:prd:session:* |
| Tenant | 生产 Tenant Key 不为空且与目标飞书组织一致 |
| 流水线 | H5 注册 token 非空,流水线请求携带匹配的 X-Pipeline-Token |
| CORS | 只放行 BeeX 自有域名及明确的本地开发来源 |
| 回归 | 未登录、过期会话、错误 Tenant、直接 curl、测试/生产切换均有自动化用例 |