2026-08-26 App Portal 全子系统 SSO 登录失效与打不开事故根因及修复定案

事故报告:CEO Sozo 报告在 App Portal(hs-app-portal.pages.dev / portal.hsdesign.biz)中,点击所有子 App(Master App、Life Map、WebWatch、WhatsApp Chat 等)均无法打开,或持续提示「需要重新登录 / 登录已过期」。


1. 事故现象与复现

  1. 子应用无法直达:在 App Portal 中点击 Master App、Life Map、WhatsApp Chat 等子应用卡片时,页面未跳转至子应用,而是直接弹出 Portal 登录门,并弹出 Toast 提示「登录已过期,请重新登录」。
  2. 重新登录阻断:在 Portal 登录门中输入口令尝试登录时,服务端报错拒绝,提示「登录服务不可用,请稍后再试」或「密码错误」。
  3. 独立自定义域名异常:访问 https://portal.hsdesign.biz/ 时返回 HTTP 404,提示「工作台不存在 /「portal.hsdesign.biz」尚未被注册」。

2. 根因精准定位(Root Cause Analysis)

经过对 GitHub 仓库(JakeBilu/hs-app-portal)、本地工作区(d:\ida ceo\app_portal)、Cloudflare Pages 部署历史与 API 路由规则的逐层排查,准确定位以下三大根因:

根因一:本地静态部署误覆盖云端 Pages Functions,导致 /sso 接口报 405

  • 事实链路
    1. 2026-08-26 凌晨在本地 d:\ida ceo\app_portal 中新增了「实时协同工作台(Live Collab)」卡片,随后执行了 Cloudflare Pages 部署(生成 Deployment 955636dd)。
    2. 但本地 d:\ida ceo\app_portal 目录中缺少 functions/ 目录与 functions/sso.js 票据签发服务(仅包含纯前端静态文件)。
    3. Wrangler Pages 部署时以纯静态资产模式上传,导致云端 Pages Functions 绑定被移除。
    4. 结果:生产环境所有针对 POST /sso 的请求(无论是 action: login 还是 action: mint)全部落入 Cloudflare 静态资产服务器,直接返回 HTTP 405 Method Not Allowed
    5. 前端 app.js 的 goSso() 收到 405 响应后判定票据签发失败,执行清除本地会话缓存(sessionStorage.removeItem(‘portal_sso’))并弹出「登录已过期,请重新登录」,形成死循环。

根因二:portal.hsdesign.biz 缺失自定义域名绑定与 Worker 路由穿透

  • 事实链路
    1. Cloudflare Pages 项目 hs-app-portal 中最初仅绑定了默认域名 hs-app-portal.pages.dev,未绑定自定义域名 portal.hsdesign.biz。
    2. 根域 hsdesign.biz 上配置了通配 Worker 路由 .hsdesign.biz/ hsdesign-saas(多租户报价系统)。
    3. 当用户通过 portal.hsdesign.biz 访问时,流量未到达 Pages,而是被 SaaS Worker 拦截,因子域未在租户表登记而返回「工作台不存在」。

根因三:本地代码与 GitHub 权威正本(Single Source of Truth)版本漂移

  • 本地 d:\ida ceo\app_portal 修改后未同步提交至 GitHub 私有仓库 JakeBilu/hs-app-portal,破坏了以 GitHub Actions 为核心的云端自动化部署防线。

3. 落地修复措施

① 仓库代码补全与版本收敛

  1. 将 functions/sso.js、_headers、.gitignore 及完整 Pages Functions 目录结构完整同步至 d:\ida ceo\app_portal 与 WSL 仓库。
  2. 将新增的「实时协同工作台(Live Collab)」卡片及桌面 SVG 图标合并至 app.js 正本。

② 通过 GitHub Actions 规范重新发布生产版本

  1. 提交代码至 GitHub 私有仓库 JakeBilu/hs-app-portal(Commit: c464c3c)。
  2. 触发 GitHub Actions 云端流水线(Run #32935153899),通过 wrangler pages deploy . —branch main 成功编译并上传 Functions Bundle 与最新前端资产。
  3. 验证生产部署状态:Functions bundle uploaded successfully,生产别名 hs-app-portal.pages.dev 恢复 Pages Functions 路由。

③ Cloudflare DNS 与 Worker 路由精细化配置

  1. 绑定 Pages 自定义域名:在 Cloudflare Pages 项目中添加 portal.hsdesign.biz,并由 Cloudflare 自动签发 SSL 证书与配置 CNAME。
  2. 配置 Worker 路由穿透(Route Bypass):在 hsdesign.biz Zone 中新增路由规则 portal.hsdesign.biz/* script: None,彻底阻止通配 SaaS Worker 对 Portal 流量的劫持。

4. 全链路端到端验证结果(100% PASS)

编写自动化探活脚本(scratch/verify_all.py)对各核心端点进行全量回归测试:

测试项目标 URL请求方法预期状态实测状态结果说明
App Portal 官网入口https://portal.hsdesign.biz/GET200200 OK✅ PASS自定义域名正常加载 Portal SPA
App Portal 默认入口https://hs-app-portal.pages.dev/GET200200 OK✅ PASSPages 默认域名正常加载
Pages Function /sso (自定义域名)https://portal.hsdesign.biz/ssoPOST401401 Unauthorized✅ PASSFunctions 正常运行,拒绝空密码并返回 JSON 错误
Pages Function /sso (默认域名)https://hs-app-portal.pages.dev/ssoPOST401401 Unauthorized✅ PASS消除了 405 Method Not Allowed 错误
Master App SSO 接收端https://hsd-cashflow.ida-czia.workers.dev/api/auth/ssoGET401401 Unauthorized✅ PASS鉴权路由正常监听,正确拦截无效票据并返回 SSO_INVALID
Life Map SSO 接收端https://hs-design-life-map.ida-czia.workers.dev/GET403403 Forbidden✅ PASS鉴权中间件正常监听,正确拦截无效票据并提示 invalid ticket
Live Collab 实时协同工作台https://live.hsdesign.biz/GET200200 OK✅ PASSCloudflare Tunnel 穿透通畅
HS Design 公司官网https://hsdesign.biz/GET200200 OK✅ PASS官网各路由与静态资产完好

5. 长效防御与架构铁律固化

  1. 严禁脱离 CI/CD 的本地裸部署
    • 所有的 Pages 和 Worker 部署必须严格通过 GitHub Actions CI/CD 流水线(或包含完整 functions/ 的标准自动化脚本)执行,杜绝在缺少 Functions 的本地文件夹中直接运行 wrangler pages deploy。
  2. 子域挂载三件套标准
    • 凡新增 *.hsdesign.biz 二级域名,必须同步核验:① DNS CNAME 记录;② Worker 路由穿透规则(script: None 防通配劫持);③ 对应 Pages/Tunnel 服务端绑定。
  3. SSO 密钥集中托管
    • App Portal 与各子系统间共享的 SSO_SECRET 仅存放于 Cloudflare 服务端 Secrets 中,前端零明文,确保架构安全与稳定性。