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. 事故现象与复现
- 子应用无法直达:在 App Portal 中点击 Master App、Life Map、WhatsApp Chat 等子应用卡片时,页面未跳转至子应用,而是直接弹出 Portal 登录门,并弹出 Toast 提示「登录已过期,请重新登录」。
- 重新登录阻断:在 Portal 登录门中输入口令尝试登录时,服务端报错拒绝,提示「登录服务不可用,请稍后再试」或「密码错误」。
- 独立自定义域名异常:访问 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
- 事实链路:
- 2026-08-26 凌晨在本地 d:\ida ceo\app_portal 中新增了「实时协同工作台(Live Collab)」卡片,随后执行了 Cloudflare Pages 部署(生成 Deployment 955636dd)。
- 但本地 d:\ida ceo\app_portal 目录中缺少 functions/ 目录与 functions/sso.js 票据签发服务(仅包含纯前端静态文件)。
- Wrangler Pages 部署时以纯静态资产模式上传,导致云端 Pages Functions 绑定被移除。
- 结果:生产环境所有针对 POST /sso 的请求(无论是 action: login 还是 action: mint)全部落入 Cloudflare 静态资产服务器,直接返回 HTTP 405 Method Not Allowed。
- 前端 app.js 的 goSso() 收到 405 响应后判定票据签发失败,执行清除本地会话缓存(sessionStorage.removeItem(‘portal_sso’))并弹出「登录已过期,请重新登录」,形成死循环。
根因二:portal.hsdesign.biz 缺失自定义域名绑定与 Worker 路由穿透
- 事实链路:
- Cloudflare Pages 项目 hs-app-portal 中最初仅绑定了默认域名 hs-app-portal.pages.dev,未绑定自定义域名 portal.hsdesign.biz。
- 根域 hsdesign.biz 上配置了通配 Worker 路由 .hsdesign.biz/ → hsdesign-saas(多租户报价系统)。
- 当用户通过 portal.hsdesign.biz 访问时,流量未到达 Pages,而是被 SaaS Worker 拦截,因子域未在租户表登记而返回「工作台不存在」。
根因三:本地代码与 GitHub 权威正本(Single Source of Truth)版本漂移
- 本地 d:\ida ceo\app_portal 修改后未同步提交至 GitHub 私有仓库 JakeBilu/hs-app-portal,破坏了以 GitHub Actions 为核心的云端自动化部署防线。
3. 落地修复措施
① 仓库代码补全与版本收敛
- 将 functions/sso.js、_headers、.gitignore 及完整 Pages Functions 目录结构完整同步至 d:\ida ceo\app_portal 与 WSL 仓库。
- 将新增的「实时协同工作台(Live Collab)」卡片及桌面 SVG 图标合并至 app.js 正本。
② 通过 GitHub Actions 规范重新发布生产版本
- 提交代码至 GitHub 私有仓库 JakeBilu/hs-app-portal(Commit: c464c3c)。
- 触发 GitHub Actions 云端流水线(Run #32935153899),通过 wrangler pages deploy . —branch main 成功编译并上传 Functions Bundle 与最新前端资产。
- 验证生产部署状态:Functions bundle uploaded successfully,生产别名 hs-app-portal.pages.dev 恢复 Pages Functions 路由。
③ Cloudflare DNS 与 Worker 路由精细化配置
- 绑定 Pages 自定义域名:在 Cloudflare Pages 项目中添加 portal.hsdesign.biz,并由 Cloudflare 自动签发 SSL 证书与配置 CNAME。
- 配置 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/ | GET | 200 | 200 OK | ✅ PASS | 自定义域名正常加载 Portal SPA |
| App Portal 默认入口 | https://hs-app-portal.pages.dev/ | GET | 200 | 200 OK | ✅ PASS | Pages 默认域名正常加载 |
| Pages Function /sso (自定义域名) | https://portal.hsdesign.biz/sso | POST | 401 | 401 Unauthorized | ✅ PASS | Functions 正常运行,拒绝空密码并返回 JSON 错误 |
| Pages Function /sso (默认域名) | https://hs-app-portal.pages.dev/sso | POST | 401 | 401 Unauthorized | ✅ PASS | 消除了 405 Method Not Allowed 错误 |
| Master App SSO 接收端 | https://hsd-cashflow.ida-czia.workers.dev/api/auth/sso | GET | 401 | 401 Unauthorized | ✅ PASS | 鉴权路由正常监听,正确拦截无效票据并返回 SSO_INVALID |
| Life Map SSO 接收端 | https://hs-design-life-map.ida-czia.workers.dev/ | GET | 403 | 403 Forbidden | ✅ PASS | 鉴权中间件正常监听,正确拦截无效票据并提示 invalid ticket |
| Live Collab 实时协同工作台 | https://live.hsdesign.biz/ | GET | 200 | 200 OK | ✅ PASS | Cloudflare Tunnel 穿透通畅 |
| HS Design 公司官网 | https://hsdesign.biz/ | GET | 200 | 200 OK | ✅ PASS | 官网各路由与静态资产完好 |
5. 长效防御与架构铁律固化
- 严禁脱离 CI/CD 的本地裸部署:
- 所有的 Pages 和 Worker 部署必须严格通过 GitHub Actions CI/CD 流水线(或包含完整 functions/ 的标准自动化脚本)执行,杜绝在缺少 Functions 的本地文件夹中直接运行 wrangler pages deploy。
- 子域挂载三件套标准:
- 凡新增 *.hsdesign.biz 二级域名,必须同步核验:① DNS CNAME 记录;② Worker 路由穿透规则(script: None 防通配劫持);③ 对应 Pages/Tunnel 服务端绑定。
- SSO 密钥集中托管:
- App Portal 与各子系统间共享的 SSO_SECRET 仅存放于 Cloudflare 服务端 Secrets 中,前端零明文,确保架构安全与稳定性。