如何在Angular拦截器中调用Refresh Token API刷新访问令牌?
Angular拦截器内调用刷新Token接口实现方案
要实现先刷新Token再发送原请求的逻辑,核心要注意避免刷新Token接口被当前拦截器拦截造成死循环,再借助RxJS操作符实现请求串行处理即可,以下是完整实现:
修改后完整拦截器代码
import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpClient } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { switchMap, catchError } from 'rxjs/operators'; import { Router } from '@angular/router'; // 可选,用于刷新失败跳登录页 @Injectable() export class TokenInterceptor implements HttpInterceptor { constructor( private http: HttpClient, private router: Router // 可选注入 ) {} intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { // 1. 放行刷新Token的请求,避免循环调用 if (request.url.includes('/api/refresh-token')) { return next.handle(request); } // 2. 校验Token是否需要刷新,可自行替换校验逻辑 const needRefresh = this.checkTokenNeedRefresh(); const accessToken = localStorage.getItem('access_token'); // 3. 不需要刷新直接携带原有Token发送请求 if (!needRefresh && accessToken) { request = request.clone({ setHeaders: { Authorization: `Bearer ${accessToken}` } }); return next.handle(request); } // 4. 需要刷新Token,先调用刷新接口再发送原请求 return this.http.post('/api/refresh-token', { refresh_token: localStorage.getItem('refresh_token') }).pipe( switchMap((res: any) => { // 存储新返回的Token和有效期 localStorage.setItem('access_token', res.access_token); localStorage.setItem('refresh_token', res.refresh_token); localStorage.setItem('token_expire_time', String(Date.now() + res.expires_in * 1000)); // 克隆原请求,携带新Token const newRequest = request.clone({ setHeaders: { Authorization: `Bearer ${res.access_token}` } }); // 发送原请求 return next.handle(newRequest); }), catchError(err => { // 刷新Token失败,清除本地信息跳转到登录页 localStorage.clear(); this.router.navigate(['/login']); return throwError(() => err); }) ); } // 自定义Token有效期校验逻辑,示例为提前5分钟刷新 private checkTokenNeedRefresh(): boolean { const expireTime = Number(localStorage.getItem('token_expire_time')); if (!expireTime) return true; // 剩余有效期小于5分钟触发刷新 return Date.now() > expireTime - 5 * 60 * 1000; } }
核心注意点
- 接口路径替换:代码里的
/api/refresh-token需要替换成你自己业务的刷新Token接口地址 - 避免死循环:必须先判断当前请求是不是刷新Token的接口,直接放行,否则刷新请求也会被拦截器拦截,再次触发刷新逻辑造成死循环
- 错误处理:刷新Token失败后要及时清除本地存储的用户信息,跳转到登录页避免异常状态
- 多请求并发优化(可选):如果同时有多个请求触发Token刷新,可以加全局锁避免重复调用刷新接口,所有等待的请求等刷新完成后再依次发送。
内容的提问来源于stack exchange,提问作者Ajay
相关产品推荐
相关产品推荐

