我已经为新的 HttpClient 实现了 http 拦截器,并且一切正常,令牌会针对单个请求进行刷新,但是如果我尝试访问从两个 api 延迟加载数据的路由,我会收到一个错误,并且我的 JWT 令牌被列入黑名单。
Laravel 后端令牌刷新方法:
public function refreshToken() {
$token = \JWTAuth::getToken();
if (! $token) {
return response()->json(["error" => 'Token is invalid'], 401);
}
try {
$refreshedToken = \JWTAuth::refresh($token);
$user = \JWTAuth::setToken($refreshedToken)->toUser();
} catch (JWTException $e) {
return response()->json(["error" => $e->getMessage()], 400);
}
return response()->json(["token" => $refreshedToken, "user" => $user], 200);
}
Angular Http 拦截器:
@Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
constructor(private injector: Injector) { }
intercept(request: HttpRequest<any>, next: HttpHandler) : Observable<HttpEvent<any>> {
return next.handle(request).catch((errorResponse: HttpErrorResponse) => {
const error = (typeof errorResponse.error !== 'object') ? JSON.parse(errorResponse.error) : errorResponse;
if(errorResponse.status === 401 && error.error === 'token_expired') {
const http = this.injector.get(HttpClient);
let token = localStorage.getItem('token');
return http.post<any>(`${environment.apiBaseUrl}token/refresh`, {},
{headers: new HttpHeaders().set('Authorization', `Bearer ${token}`)})
.flatMap(data => {
localStorage.setItem('currentUser', JSON.stringify(data));
localStorage.setItem('token', data.token);
const cloneRequest = request.clone({setHeaders: {'Authorization': `Bearer ${data.token}`}});
return next.handle(cloneRequest);
});
}
return Observable.throw(errorResponse);
});
}
}
我使用解析器的路线:
{
path: '',
children: [ {
path: 'create',
component: CreateCarComponent,
resolve: {
subcategories: SubCategoriesResolver,
companies: CompaniesResolver
}
}]
}
公司解析器:(汽车解析器与此类似)
@Injectable()
export class CompaniesResolver implements Resolve<any> {
constructor(private _userService: UserService) {}
resolve(route: ActivatedRouteSnapshot) {
return this._userService.getCompaniesList();
}
}
用户服务方法示例:
getUserCardsApi: string = "user/cars/all";
getCardsList() : Observable<any[]> {
return this._http.get(environment.apiBaseUrl + this.getUserCardsApi, this.jwtHeaders())
.catch(error => {
return Observable.throw(error);
});
}
标题:
private jwtHeaders() {
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
return {headers: new HttpHeaders().set('Authorization', 'Bearer ' + currentUser.token)}
}
}
每当我使用超过 2 个解析器访问路由时,我收到的第一个响应是正确的,并返回一个带有用户对象的刷新令牌,之后的下一个响应立即返回被列入黑名单的令牌。您能否建议可能是什么问题,我花了太多时间来解决这个问题(
更新1:
我注意到第二次刷新请求传递的是旧令牌而不是新令牌,这就是 Laravel 将令牌列入黑名单的原因