Sunday面试指南

JWT 无感刷新怎么实现?多个请求同时 401 怎么办?

下面是一段教学用的模拟面试。

🧑‍💻 面试官:Access Token 过期了,怎么让用户继续操作,不用重新登录?

🙋‍♂️ 我:收到 401 后,用 Refresh Token 换一个新的 Access Token,再重发原请求。

🧑‍💻 面试官:页面同时请求用户信息、通知和列表,三个请求都返回 401,要刷新三次吗?

🙋‍♂️ 我:应该把刷新合并,其他请求等同一个结果。

🧑‍💻 面试官:刷新失败了怎么办?还有一个请求拿着旧 Token,等你刷新成功以后才返回 401,它要再刷新一次吗?

答好这道题,要把刷新看成一次需要协调的操作。谁负责刷新、谁等待结果、什么情况结束登录,都要有明确规则。

面试速答(60 秒版)

无感刷新通常会配合两种凭据。Access Token 用来访问业务接口,有效期较短;Refresh Token 用来申请新的 Access Token,需要单独保护和撤销机制。

当业务接口明确返回访问凭据过期时,客户端启动刷新。多个请求同时遇到这个问题,只让一个请求负责刷新,其余请求等待同一个结果。刷新成功后,保存新凭据,再按规则重发原请求。

重试也要有上限。刷新接口不能进入自己的刷新拦截器,原请求最多自动重试一次。Refresh Token 失效或被撤销时,结束当前登录状态。网络暂时失败则给出可恢复的错误,不能一律把用户登出。

同时,还要识别晚到的旧 401。如果当前凭据已经更新,先用新凭据重试,不必再刷新。涉及写操作时,服务端仍需要幂等保护,不能靠客户端自动重发保证安全。

多个过期请求共享一次续期,客户端用Refresh Token换取新的Access Token

知识点详解:让一批过期请求共享一次刷新

两个 Token 分别负责什么?

假设用户打开后台页面,客户端带着 Access Token 查询用户信息。服务端验证签名、有效期和访问范围,通过后才处理业务。

Access Token 过期以后,业务接口不再接受它。客户端把续期请求发给专门的认证接口,由认证服务检查 Refresh Token 和当前会话,决定是否发放新凭据。

因此,Refresh Token 并不应该附在每个业务请求里。它更适合由认证服务或 BFF 管理;如果使用 Cookie,还要配置 HttpOnly、Secure、合适的 SameSite,并处理跨站请求风险。HttpOnly 能限制脚本读取,不能阻止已经运行在页面里的恶意脚本发起请求。

Refresh Token 可以采用不透明随机串,也可以使用其他受控格式,名称里有 Token 不代表它必须是 JWT。

三个请求一起失败,怎么只刷新一次?

客户端可以保存一个“正在刷新”的共享结果。在 JavaScript 中通常是一个 Promise,在其他异步运行时可以是共享 Future 或 Task。

第一个遇到过期错误的请求发现没有刷新任务,于是创建它。后来的请求发现已经在刷新,就等待这份结果。这里等待的是同一次认证请求,不是每个请求各自睡一会儿再试。

刷新成功以后,客户端先替换凭据,再唤醒等待者。失败时,等待者也要收到失败结果,不能永远卡在 loading。

当前情况客户端如何处理
凭据过期,尚未开始刷新创建共享刷新任务
凭据过期,已经有刷新任务等待已有任务
刷新成功安装新凭据,再重试原请求
认证服务确认会话失效清理登录状态,要求重新认证
网络或认证服务临时故障返回可恢复错误,按有限策略重试

这个共享任务要在完成后释放,成功和失败都要清理。否则后续请求可能一直复用一份已经失败的结果。

晚到的 401,为什么不能直接再刷新?

假设 A、B 都带着凭据 v1 出发。A 很快返回过期错误,完成刷新,客户端现在已经换成 v2。B 的旧响应这时才回来。

如果 B 只看状态码,又会发起一轮刷新。

咱们可以在发请求时记下凭据版本。收到过期响应后,比较这个版本和当前版本。已经换过凭据,就先用新凭据重试;版本没变,才进入刷新协调流程。

用户退出或切换账号时,也要让登录版本变化。旧刷新请求稍后成功,不能把上一个账号的凭据装回当前页面。请求属于哪一次登录,比“最后一个响应赢”更重要。

A刷新得到v2以后,B旧请求的迟到401只触发使用v2的有限重试

为什么不是所有 401 都需要刷新?

401 只说明当前认证没有通过。凭据缺失、格式错误、签名错误和过期,都可能返回这个状态。

因此接口需要约定可识别的错误类型,例如访问凭据过期才允许续期。权限不足通常按授权错误处理,刷新凭据也不会凭空增加权限。

刷新接口必须绕开自动刷新逻辑,原请求也需要携带“已经重试”的标记。如果新凭据仍然被拒绝,就把错误交给调用方处理,不能形成无限循环。

服务端还需要防什么?

Refresh Token 轮换会在续期时发放新凭据,并使旧凭据失效。客户端的并发协调尤其重要,否则正常的多个刷新请求也可能撞上重复使用检测。具体失效与宽限规则要按认证系统确认,不能自己猜。

这部分机制可参考 Auth0 的 Refresh Token Rotation 文档。本文里的共享任务与凭据版本,是客户端协调方案,不代表 Auth0 自动替所有自建客户端完成这些工作。

至于自动重发写请求,需要确认失败发生在哪一步。服务端应在执行业务前完成鉴权,并用业务幂等键保护可重复提交的动作。支付请求超时后结果未知,不能套用“刷新后再发一次”来解决。

面试官继续追问

同时打开两个标签页,共享 Promise 还管用吗?

共享 Promise 只覆盖当前 JavaScript 运行环境。跨标签页可以结合 Web Locks、BroadcastChannel 或由 BFF 统一协调,但要处理锁释放、页面退出和消息丢失。浏览器 API 的支持范围也需要核对。

提前刷新是不是就没有并发问题了?

提前刷新可以减少接口恰好过期的概率,但多个标签页、时钟偏差和凭据撤销仍然可能出现。主动续期与收到过期响应后的处理,可以配合使用。

怎么验证方案没有漏掉异常?

让一批请求同时遇到过期错误,检查刷新次数;再让旧响应晚到、刷新请求失败、用户中途退出。最后确认没有无限重试、没有请求一直等待,也没有把旧账号凭据写回来。日志记录会话和请求关联信息,别记录完整 Token。

面试速记卡

  • Access Token 访问业务,Refresh Token 负责受控续期。
  • 并发过期请求等待同一个刷新结果。
  • 晚到的旧响应先检查凭据版本。
  • 刷新接口绕开拦截器,原请求限制重试次数。
  • 会话失效与临时网络故障分别处理。
  • 写请求另做幂等,退出登录后拒绝旧刷新结果。

公司面试真题

真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。

浏览公司面试真题 →
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历