因为专注所以专业
助力成长与创新,汇集前沿前端开发观点

2026年了,后台首屏几个接口一起报 401,连刷新 token 的请求也 401,是拦截器把自己也拦了吗?

2026年10月23日 阅读:115

结论先说:2026 年 Angular 项目里 token 一过期就疯狂重试,通常不是刷新接口本身坏了,而是两件事叠在一起:刷新 token 的请求也被同一个拦截器拦下,形成 401→刷新→又 401 的递归;首屏并发请求各自收到 401 后又没有排队,同时触发多次刷新。更稳的做法是让刷新请求走独立 HttpClient 或白名单跳过,并发 401 只允许一个刷新在飞,其余请求挂起,拿到新 token 后再重放。

先看三个触发点,别只盯着刷新接口

很多团队第一反应是查刷新接口返回值,但交付现场更常见的是拦截器没区分「业务请求」和「刷新请求」。先把触发点定位清楚,再谈排队,能少走一半弯路。

  • 刷新请求被自己拦截:刷新 token 用的是同一个 HttpClient,拦截器把它也当成需要鉴权的请求,401 处理逻辑自己调用自己。
  • 并发 401 各自刷新:后台首屏常见同时发 6~8 个接口,旧 token 过期后一起返回 401,每个都去调刷新接口,结果互相覆盖。
  • 刷新失败后没停:刷新接口本身失败时,兜底逻辑又触发重试或路由跳转,路由守卫再发请求,形成另一条循环。

判断是否命中这三类问题,可以看浏览器网络面板:刷新接口短时间被调用多次,或刷新接口自身也返回 401,基本可以确认拦截器递归与并发未排队同时存在。

交付现场:首屏并发 401,用户被连续踢出

在一个后台管理系统项目里,约束很典型:仪表盘首屏并发 6~8 个接口,token 有效期偏短,联调环境里旧 token 过期后集中返回 401。原来的拦截器对每个 401 都直接调刷新接口,刷新请求又走同一个 HttpClient,日志里很快出现成串 401,用户被连续跳了三次登录页。

后来的做法是给刷新请求单独建一个不带该拦截器的 HttpClient 实例,同时在拦截器里按 URL 白名单跳过刷新与登录接口;并发 401 用单飞 Observable 加等待队列,队列超时放在 8~15 秒的经验区间。结果是并发 401 只触发一次刷新,原请求重放成功,用户不再被连续踢出。代价是拦截器多了一层状态管理,后续同事接手要先看注释,否则容易把白名单删掉,问题会重新出现。

三种做法怎么取舍:别为两个接口上队列

方案没有绝对好坏,关键看并发量和 token 生命周期。2026 年常见的三种做法对比如下,工作量为经验区间,视拦截器数量和并发场景而定。

  • 方案 A 拦截器内直接刷新:常见 0.5~1 人天;适合接口少、并发低、token 有效期覆盖单次会话的小项目。不适合首屏多接口并发或 token 很短的后台系统。
  • 方案 B 独立认证服务加单飞队列:常见 1~3 人天;适合多接口并发、需要无感续期的后台系统。要维护队列、超时和失败兜底,复杂度高一些。
  • 方案 C 路由守卫预刷新:常见 0.5~1 人天;适合页面级跳转前续期。不适合页面内长时间停留、定时轮询或弹窗内连续请求的场景。

如果项目里已有统一认证服务,优先把单飞逻辑放进服务,而不是散在拦截器里;如果只是几个公开页面加一个登录态,方案 A 加白名单跳过通常够用,不必为排队引入额外状态。

上线前按这几条验收

验收 401 处理不能只看「能刷新」,要看并发和失败路径。下面几条可以作为可测口径。

  • 并发 5 个请求同时 401 时,刷新接口只被调用 1 次,其余请求在队列里等待。
  • 刷新请求不出现在拦截器的 401 递归日志里,刷新接口自身返回 401 时不再触发刷新。
  • 刷新失败后只跳转 1 次登录页,等待队列里的请求直接失败返回,不重复跳转。
  • 重放请求保留原 method、body 和业务头,只替换 Authorization;POST 不出现空 body。
  • 等待队列有超时,常见 8~15 秒,避免刷新接口挂起时页面一直转圈。

常见坑集中在白名单和重放两处:白名单按 URL 包含匹配太宽,会把业务接口也跳过;重放时新建请求只带 URL 和 header,漏掉 body,POST 就变成空提交。另一个高频问题是刷新成功后没更新本地存储,用户手动刷新页面又拿到旧 token。

适用与不适用边界

适合上单飞刷新与等待队列的情况:后台系统首屏并发接口较多、token 有效期较短、需要用户无感续期、刷新接口本身也需要鉴权。公开内容页、以 Cookie 会话为主的站点,通常不必照搬。

不适合的情况也要写清楚:token 有效期覆盖单次使用且接口很少的小项目,上队列反而增加维护成本;页面内只有一两个请求、很少遇到并发 401 的场景,先做白名单跳过更划算。

边界句:如果项目只有 1~2 个接口且 token 有效期覆盖单次会话,先用白名单跳过刷新请求即可,单飞队列不是必选项。是否升级到队列,看并发 401 是否真实出现、是否造成重复刷新或连续踢登录,而不是看框架版本。

常见问题

Angular 拦截器里怎么让刷新 token 的请求不再次被拦截?

常见做法是给刷新请求单独建一个不带该拦截器的 HttpClient 实例,或在拦截器里按 URL 白名单和自定义头跳过;两者选其一,别只靠 URL 包含判断。

多个接口同时 401,怎么保证只刷新一次 token?

用一个共享的 refreshInFlight Observable 做单飞,第一个 401 发起刷新,其余请求订阅同一个流,等新 token 到了再重放,避免各自调用刷新接口。

刷新 token 失败后,为什么页面会连续跳好几次登录页?

并发 401 各自走了失败分支,每个都执行跳转。兜底逻辑要加已跳转标记,或只让刷新发起方处理跳转,其余等待请求直接失败返回。

拦截器里重放原请求,为什么 POST 的 body 丢了?

常见是重放时新建了请求只带 URL 和 header,没把原 request.body 和 method 带过去;用 clone 并显式设置 body 和 setHeaders 更稳妥。

用 HttpInterceptorFn 和类拦截器,处理 401 有区别吗?

函数式拦截器靠 inject 拿依赖,单飞状态要放在可注入服务里而不是模块级变量;类拦截器同理,差别主要在写法,并发排队逻辑一致。


如果接下来要改现有拦截器,建议先按「识别、排队、重放、兜底」四步做一次代码走查,再用并发 5 个 401 的联调场景验收。适用边界也要提前说清:公开页面和 Cookie 会话站点不必照搬单飞队列,按实际并发与 token 生命周期取舍即可。

有类似的项目需求?
联系我们,获取一对一项目参考方案
获取方案
对这个话题感兴趣?
10 年技术团队,24 小时内出具参考方案
获取方案
准备好开始了吗,
那就与我们取得联系吧!
13370032918
了解更多服务,随时联系我们
请填写您的需求
您希望我们为您提供什么服务呢
您的预算
联
系
微信二维码
扫码添加客服微信
专业对接各类技术问题
联系电话
13370032918 (金经理)
电话若占线或未接到、就加下微信
联系邮箱
349077570@qq.com
提交成功
感谢您的信任,我们会尽快与您联系!
为您推荐以下案例