我有一个系统,我将一个刷新令牌(长寿命)和一个访问令牌(短期)返回给Angular前端。
目前,仅设置访问令牌。
我有HttpInterceptor
设置,我按照这样注入访问令牌:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let token = this.somewhere.getToken();
let requestToHandle: HttpRequest<any> = req;
if (token != null && token.length > 0) {
const clonedRequest = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + token) });
requestToHandle = clonedRequest;
}
return next.handle(requestToHandle).catch((err: HttpErrorResponse) => {
// some error handling here
});
}
现在我正在添加刷新令牌,我希望系统在我们获得401(内部.catch()
块)时尝试为访问令牌交换刷新令牌。
但是,由于循环依赖,我无法向我的拦截器注入HttpClient
。 (我也尝试使用Injector
,没有运气)。
更新将Angular更新为5.2.9后,我实际上可以注入HttpClient
。
我添加了这样的代码:
return next.handle(requestToHandle).catch((err: HttpErrorResponse) => {
if (!(err.error instanceof Error)) {
if (err.status === 401) {
this.http.post<Token>('http://somewhere' + '/somerfreshtokenapi',
{
refresh_token: this.someService.refreshToken
}).subscribe(result => {
let requestClone = requestToHandle.clone({ headers: req.headers.set('Authorization', 'Bearer ' + result.token) });
requestToHandle = requestClone;
// how do i wire this back to `next.handle()`?
return this.httpClient.request(requestToHandle);
}, e => {
// some error handling here
});
});
}
return Observable.throw(err);
});
答案 0 :(得分:1)
只需使用switchMap
而不是订阅,并使用新令牌执行失败的请求:
if (err.status === 401) {
this.http.post<Token>(...)
.switchMap(result => {
let requestClone = requestToHandle.clone({ headers: req.headers.set('Authorization', 'Bearer ' + result.token) });
return next.handle(requestClone)
}, e => {
// some error handling here
});
}
答案 1 :(得分:-1)
只需进行递归通话?
return next.handle(requestToHandle).catch((err: HttpErrorResponse) => {
if(err && err.status === 401) {
const clone = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + refreshedToken) });
return this.intercept(clone, next);
}
return Observable.throw(err);
});