重新走一遍登录用了 20 秒,读懂那个 403 响应体用了半小时

举报
yd_48584989 发表于 2026/11/03 08:44:30 2026/11/03
【摘要】 身份接口返回 403 的时候,页面本身还在正常渲染,静态资源全是 200——这两件事同时成立,所以我第一反应是「网络问题」。真正有用的是 403 的响应体:两个不同的字段名,分别指向网关和应用两个不同的失效层。

早上打开自己写的一个控制台工具,页面照常渲染:logo、菜单、卡片全都出来了, 静态资源一条 200 都没少。但所有需要登录态的接口都返回了同一个状态码:403。

页面能开、接口全 403,这两件事同时成立的时候,最容易得出的结论是「网络抖动,重试一下」。 我重试了三次,403 一次都没变。状态码不变,说明这不是抖动。

403 的响应体里有两句不同的话

把响应体原样打出来,事情就清楚了。同一套接口,两种不同的 body:

// 第一种
HTTP/1.1 403 Forbidden
{"error_b_msg": "not login"}

// 第二种
HTTP/1.1 403 Forbidden
{"error_msg": "token not found"}

状态码一样,字段名不一样:一个是 error_b_msg,一个是 error_msg。 在我对接的这套体系里,这两个前缀对应不同的一层:

响应体字段 拒绝发生在 含义
error_b_msg 网关/单点登录层 请求根本没带上有效的票据,网关直接挡掉
error_msg 应用层 票据收到了,但应用侧拿不到对应的 token

这个区别不是文字游戏。第一种情况,重新走一遍登录流程就能拿到新票据;第二种情况, 票是新的、但应用侧的 token 已经不是同一个了,这时候只重新登录、不清掉旧的会话数据, 下一次请求大概率还是 403——看起来像「登录没用」。

页面为什么还能开

这是我当时判断错的地方,值得单独记一笔。页面能渲染,只说明 HTML 和静态资源能拿到; 它们走的是另一个域名、另一套缓存策略,跟接口的会话 credential 不是一件事。 把「页面能打开」当作「会话有效」的证据,等于用 A 系统的可用性去推断 B 系统的登录态。

同理,反过来也不成立:接口 200 不代表页面没问题。判据只能落在同一个东西上—— 身份接口自己的返回。

两次重新登录的实际耗时

把时间戳记下来之后,这事的量级和我猜的完全不一样。从打开登录页到身份接口重新返回 200, 两次分别是 20 秒 和 21 秒。也就是说,登录本身根本不慢; 前面那半小时全花在「这到底是网络问题还是会话问题」的分辨上。

耗时分布大概是这样的:分辨现象半小时,动手修复二十秒。这个比例说明排查的方向找错了, 而找错方向的原因只有一个——我一开始没有把响应体打出来,只看了状态码。

现在这段判据写成了这样

不再问「页面还在不在」,直接问身份接口,并且要求返回 200 加上业务字段齐全:

const r = await fetch(API.me, { credentials: 'include' });
const text = await r.text();

if (r.status === 403) {
  // 403 一定要把 body 留着,字段名比状态码有信息量
  console.warn('403 body:', text);
  return { state: 'expired', layer: text.includes('error_b_msg') ? 'sso' : 'app' };
}
if (!r.ok) return { state: 'error', status: r.status };

const data = JSON.parse(text);
return data && data.name ? { state: 'ok', name: data.name } : { state: 'unknown' };

这段代码里最没技术含量的一行其实是 console.warn('403 body:', text), 但它是最有用的:没有这一行,我连「有两种 403」这件事都不会知道。

可以拿走的三条

  1. 404/403 只是 HTTP 层的分类,真正的原因写在响应体里。抓 403 的时候把 body 原样留下来, 否则你面对的是一个只有状态码的黑盒。
  2. 「页面能渲染」和「会话有效」是两个独立事实。判断登录态只认身份接口:200 + 业务字段齐全, 两个条件缺一不可。
  3. 失效层不同,处置不同:网关层没票,重新走登录;应用层 token 缺失,得先清掉旧会话数据再登录, 不然重登也是空转。分清这一层,比多试几次有用得多。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。