Angular Token拦截器刷新JWT后仅重发最后一个401请求问题求解
Angular JWT令牌拦截器多请求401丢失问题修复
根因定位
你的代码核心逻辑错误出在handle401Error方法的分支处理上:
- 当已经有请求触发令牌刷新(
isRefreshing = true)时,后续进入该方法的401请求没有返回对应的Observable对象,直接被静默丢弃,所以只有第一个触发刷新的请求会被重发,其余请求全部丢失。 - 等待刷新完成后重发请求的逻辑被错误放在了
!isRefreshing分支内部,仅当刷新令牌为空时才会执行,完全不符合预期的业务逻辑。
修复代码
仅需要调整handle401Error方法的分支逻辑即可:
private handle401Error(request: HttpRequest<any>, next: HttpHandler, rToken: string) { if (!this.isRefreshing) { this.isRefreshing = true; this.refreshTokenSubject.next(null); if (rToken && rToken !== '') { const body = new URLSearchParams(); body.set('grant_type', 'refresh_token'); body.set('refresh_token', rToken); return this.authService.fetchToken$(body).pipe( switchMap((newToken: Token) => { this.isRefreshing = false; this.sessionStorageJwtService.setToken(newToken); this.refreshTokenSubject.next(newToken); return next.handle(this.addTokenHeader(request, newToken)); }), catchError((err) => { this.isRefreshing = false; this.authFacade.logout(); return throwError(err); }) ); } else { // 无有效刷新令牌直接触发登出 this.isRefreshing = false; this.authFacade.logout(); return throwError(() => new Error('无可用刷新令牌')); } } else { // 刷新过程中产生的所有401请求,等待新令牌生成后统一重发 return this.refreshTokenSubject.pipe( filter(token => token !== null), take(1), switchMap((token) => next.handle(this.addTokenHeader(request, token))) ); } }
额外优化建议
你当前获取令牌和刷新令牌的逻辑是通过subscribe订阅Observable取值,若SessionStorageJwtService的取值逻辑是异步的,可能存在取值延迟导致后续判断出错的问题,建议改为直接读取sessionStorage的同步接口取值,避免异步问题。
内容的提问来源于stack exchange,提问作者Davide Cividini
相关产品推荐
相关产品推荐

