现象
外壳页面是 /bonder/external?iframeLink=/ddus/。内容区的 iframe 不直接打开被嵌系统,而是先打开同源授权地址:
/connector/common-admin-cloud/api/authority/admin/oauth2/v2/authorize?clientId=...&redirectUri=...&authorization=...
token 有效时,这个接口会把 iframe 转到 /ddus/,被嵌页面正常起来。token 无效时,接口返回 HTTP 200,响应体是一段 JSON:
json
{"code":"60000","msg":"业务处理失败","subCode":"auth-check-error","subMsg":"登录已过期,请重新登录","success":false}
浏览器把这段 JSON 当成 iframe 里的文档画出来。被嵌系统的 HTML 和脚本都没有加载。
三层分别能不能处理
| 层级 | 结果 |
|---|---|
被嵌项目 /ddus |
页面没有启动,里面原有的 60000 跳转不会执行 |
外壳 data-dock-web |
iframe 由外壳创建,授权接口又和外壳同源,外壳能读到这段 JSON |
| 授权接口 | 浏览器打开时如果继续只返回 JSON,iframe 里就一定会先出现这段文本 |
这次改的是外壳。被嵌项目 platform-data-devops-ui 没有动。
复现
在开发者工具里改 iframe 的 src,把 authorization 末尾加上一个字符,回车。授权接口立即返回上面的 60000 JSON。
为什么会先闪出 JSON
iframe 此时已经按正常页面的尺寸显示。在开发者工具里改 src 是浏览器自己发起的导航,不会经过 Vue,外壳之前加上的「未确认前隐藏」也不会重新生效。
授权接口返回 JSON 后,浏览器收到响应就渲染。外壳只能在 iframe 的 load 里检查内容,而 load 发生在这一次渲染之后。所以错误 JSON 会先出现一帧。外壳无法在浏览器画出这份响应之前把它拦住。
为什么接着会空白再进登录
最初的处理是在 load 里直接改顶层 location,跳到 /bonder-login/。当前页先被卸掉,登录页还没回来,中间就是空白。
现在的行为
外壳在三个嵌入入口的 iframe @load 上做同一件事:
about:blank忽略。- 读到
code为60000,或subCode为auth-check-error、merchant-check-error时,立刻把 iframe 收成不可见,弹出「登录已过期,请重新登录」。 - 点击「重新登录」后,清掉 token,顶层跳到
/bonder-login/,redirect_uri使用当前外壳地址。 - 内容不是这段 JSON(包括最终跳到跨域业务页、外壳读不到文档)时,再把 iframe 显示出来。
由外壳自己更换 iframe 地址时,会先隐藏,确认内容安全后再显示,避免外壳导航过程中把错误 JSON 铺开。
边界
在开发者工具里直接改已经显示的 iframe src,浏览器仍可能先画出一帧 JSON,随后弹窗出现。点击「重新登录」之前不会离开当前页。