【发布时间】:2020-09-15 13:59:19
【问题描述】:
我正在制作 JWT 拦截器来处理 401 错误。我的想法是收集 401 之后的所有原始请求到数组,然后刷新我的令牌,然后在我的请求中添加一个新的标头。代码如下:
type CallerRequest = {
subscriber: Subscriber<any>;
failedRequest: HttpRequest<any>;
};
@Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
private refreshInProgress: boolean;
private requests: CallerRequest[] = [];
constructor(
public authService: AuthService,
public customersService: CustomersService,
private http: HttpClient
) {
this.refreshInProgress = false;
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!req.url.includes('api/')) {
return next.handle(req);
}
const observable = new Observable<HttpEvent<any>>((subscriber) => {
const originalRequestSubscription = next.handle(req)
.subscribe((response) => {
subscriber.next(response);
},
(err) => {
if (err.status === 401) {
this.handleUnauthorizedError(subscriber, req);
} else {
subscriber.error(err);
}
},
() => {
subscriber.complete();
});
return () => {
originalRequestSubscription.unsubscribe();
};
});
return observable;
}
private addToken(request: HttpRequest<any>, token: string) {
return request.clone({setHeaders: {'Authorization': `Bearer ${token}`}});
}
private handleUnauthorizedError(subscriber: Subscriber<any>, request: HttpRequest<any>) {
this.requests.push({ subscriber, failedRequest: request });
if (!this.refreshInProgress) {
this.refreshInProgress = true;
console.log('go refresh');
this.authService.refreshToken()
.pipe(
finalize(() => {
this.refreshInProgress = false;
})
)
.subscribe(
result => {
console.log(result); // <-- I cannot get here
this.repeatFailedRequests(this.authService.getAccessToken());
},
err => {
console.log(err); // <-- And cannot get here
}
)
}
}
private repeatFailedRequests(authHeader: string) {
this.requests.forEach((c) => {
const requestWithNewToken = this.addToken(c.failedRequest, authHeader);
this.repeatRequest(requestWithNewToken, c.subscriber);
});
this.requests = [];
}
private repeatRequest(requestWithNewToken: HttpRequest<any>, subscriber: Subscriber<any>) {
this.http.request(requestWithNewToken).subscribe((res) => {
subscriber.next(res);
},
(err) => {
if (err.status === 401) {
this.authService.removeTokens();
}
subscriber.error(err);
},
() => {
subscriber.complete();
});
}
}
看看我的 handleUnauthorizedError 方法。我无法在那里得到结果。
顺便说一下,这是我的 refreshToken:
refreshToken() {
return this.post('api/v0/jwt/refresh/', {refresh: this.getRefreshToken()})
.pipe(tap((tokens: Tokens) => {
this.storeTokens(tokens);
}));
}
我做错了什么,我该如何以正确的方式解决这个问题?谢谢!
添加:
如果我从这个问题Angular 4 Interceptor retry requests after token refresh(最受欢迎的答案)尝试 JWT 拦截器,我会遇到同样的问题 - 我的 RefreshToken() 结果未得到处理。
【问题讨论】:
-
@JózefPodlecki 同样的错误。我无法从我的 refreshToken() 中捕获错误或结果
标签: angular typescript ngrx