安全与故障排查
保护 Bundle 平台应用 token,并按授权链路定位入口、回跳和权限问题。
安全要求
- 使用 PKCE
S256,每次授权生成新的 verifier 和 state。 redirectUri必须与登记的应用入口同源。- 不在 URL、日志、错误上报、埋点或截图中记录 token。
- token 仅保存在 SDK client 内存中,校验
workspaceId + runtimeAppId + installId和过期时间;不要自行持久化。 - 内存保存 token 不消除 XSS 风险;必须执行内容安全策略和依赖安全检查。
- 应用停用、卸载、权限变化或用户退出时,清理本地会话。
- 后端服务只信任平台网关注入并验证过的上下文,不信任前端自行传入的
userId或workspaceId。
旧外部入口被拒绝
若启动提示“旧签名启动应用必须创建环境托管应用新版本”,或授权提示“外部托管应用必须使用自己的后台授权”,
先检查安装锁定的平台应用版本是否仍为 TRUSTED_EXTERNAL_APP。定义或版本创建成功不等于当前启动链路支持它。
按 迁移历史外部应用
更新源码、入口、SDK 和完整 Bundle 版本链;不要改成普通外链后继续申请平台 token。
环境配置读取或版本路径校验失败
如果 platform-app workspace list 只返回 /index.html,使用
platform-app workspace launch-context <resourceLocator> --workspace-id <workspaceId> --json
取得该安装的完整 accessUrl。如需检查准确版本部署或跨工作区分享,分别使用
platform-app version address 和 platform-app entry,见
三类入口查询。
检查实际入口同源的 /.well-known/baijimu-platform-application.json 是否可通过 HTTPS 直接读取,
并确认应用身份和精确 origin 与当前版本一致,SDK 7 的配置合同为 2.0.0。构建归档不能覆盖配置路径,不能把 API 或授权地址从 URL 参数补入。
出现 404、NoSuchKey 或返回 HTML 时,先区分入口类型:
- 历史
STATIC_SPA或TRUSTED_EXTERNAL_APP:按完整迁移流程创建ENVIRONMENT_HOSTED_APP新版本并升级 Bundle。无需为旧站点追加配置,也无需自行执行站点部署。 - 已安装的
ENVIRONMENT_HOSTED_APP:从当前安装返回的accessUrl访问,核对版本是否已升级、资源台账是否已验证、托管物化是否完成,再排查平台生成配置的步骤。
不要把旧站点的 404 直接解释为 CLI 缺少“配置托管入口”的命令;也不要增加硬编码网关、授权地址、公共 SaaS 默认地址或旧配置缓存。
授权页提示缺少参数
检查参数是否写在 Hash Router 路由后:
正确:https://console.baijimu.com/#/platform-app-authorize?installId=...
错误:https://console.baijimu.com/?installId=...#/platform-app-authorize分享入口提示需要安装 Bundle
这是预期的授权边界,不是平台应用缺少单独授权。确认分享地址使用 /bundle-app/{bundleId}/{platformAppId},选择正确工作区,并让工作区所有者或管理员安装提示的 Bundle。平台应用不能脱离 Bundle 单独安装。
redirectUri 不合法
检查协议、域名和端口是否与环境托管后的实际入口同源,并核对同源配置的 applicationOrigin;SDK 7 新部署不含 releasePath。清单中的 /index.html 是构建产物内路径,不能直接充当授权回跳 URL,也不能用外部域名替换托管入口。
缺少 PKCE verifier
通常是授权前没有保存 verifier、回跳进入了不同浏览器会话,或者应用刷新逻辑提前清理了 sessionStorage。重新开始授权并保证同一浏览器会话完成回跳。
state 校验失败
停止兑换 token。检查是否同时发起了多个授权请求、多个安装共用了同一个 storage key,或者回跳参数被路由层覆盖。
授权回跳后提示缺少 installId
先查看平台安装记录返回的 accessUrl,确认平台已在托管入口中追加 installId。如果首次跳转有该参数、授权回跳后却
消失,通常是应用自行执行了类似 history.replaceState({}, "", location.pathname + location.hash) 的清理逻辑,
把整个查询串连同 installId 一起删除了。
不要为此增加缓存态 installId 或从其他字段猜测安装身份。环境托管应用必须让
@baijimu/platform-application-sdk 完成回跳清理;SDK 只删除一次性的 code 和 state,保留入口身份参数。
迁移旧项目时,应同时删除自实现的 PKCE、token 缓存和 Gateway client,避免两套状态机竞争。
token 兑换失败
依次确认:
code尚未使用且没有过期。installId与发起授权时一致。codeVerifier与原始 challenge 匹配。- 请求体字段使用
code和codeVerifier。
平台切换账号后应用仍是旧用户
先核对部署产物使用的 SDK 版本。SDK 6.0.0 以前会复用应用 origin 的持久化会话,平台与应用域名的 存储不会因另一边退出自动同步。升级 SDK、删除应用自实现缓存并重新构建、创建应用版本、升级 Bundle,再重新打开应用验证。 不要把 token 的有效期当成当前平台身份的证明,也不要通过修改 userId 参数补偿错误身份。
SDK 6.0.0 新开或刷新重新授权;已打开页面的即时账号同步需要平台会话联动。排查时分别记录平台身份、 应用授权返回身份、应用版本和打开时间,不记录完整 token。
接口返回无权限
不要立即重新登录。先区分:
- App Gateway 明确拒绝会话,SDK 已清空
getSession():重新授权。 - 后端返回合法 CModel
UNAUTHORIZED:保留登录会话并展示业务错误;HTTP 401 本身不能替代 SDK 的会话判断。 - 模块方法未声明:创建包含正确最小权限的平台应用新版本。
- 工作区未安装依赖能力:修复安装或接口绑定。
- 用户没有目标业务权限:由业务权限管理员处理。
- 后端服务异常:查看目标服务日志和追踪信息。
- 安装或升级未确认跨 Bundle 方法:重新执行预览,核对精确清单后再确认;不要复用旧预览。
排障时保留 installId、runtimeAppId、平台应用版本号、模块 service、方法名和平台
返回的公开错误信息;不要保存完整 token。