我正在尝试实现对 401 响应的捕获,并尝试 在令牌刷新后根据 Angular 4 Interceptor retry requests获取刷新令牌。我试图实现同样的事情,但我永远无法重试该请求,而且我真的不确定这是否是应用刷新令牌策略的最佳方法。这是我的代码:
@Injectable()
export class AuthInterceptorService implements HttpInterceptor {
public authService;
refreshTokenInProgress = false;
tokenRefreshedSource = new Subject();
tokenRefreshed$ = this.tokenRefreshedSource.asObservable();
constructor(private router: Router, private injector: Injector) { }
authenticateRequest(req: HttpRequest<any>) {
const token = this.authService.getToken();
if (token != null) {
return req.clone({
headers: req.headers.set('Authorization', `Bearer ${token.access_token}`)
});
}
else {
return null;
}
}
refreshToken() {
if (this.refreshTokenInProgress) {
return new Observable(observer => {
this.tokenRefreshed$.subscribe(() => {
observer.next();
observer.complete();
});
});
} else {
this.refreshTokenInProgress = true;
return this.authService.refreshToken()
.do(() => {
this.refreshTokenInProgress = false;
this.tokenRefreshedSource.next();
}).catch(
(error) => {
console.log(error);
}
);
}
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.authService = this.injector.get(AuthenticationService);
request = this.authenticateRequest(request);
return next.handle(request).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// do stuff with response if you want
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
return this.refreshToken()
.switchMap(() => {
request = this.authenticateRequest(request);
console.log('*Repeating httpRequest*', request);
return next.handle(request);
})
.catch(() => {
return Observable.empty();
});
}
}
});
}
}
问题是 SwitchMap 永远无法到达......
if (err.status === 401) {
return this.refreshToken()
.switchMap(() => {
还有 do 运算符...
return this.authService.refreshToken()
.do(() => {
所以这把我带到了我的 authService refreshToken 方法......
refreshToken() {
let refreshToken = this.getToken();
refreshToken.grant_type = 'refresh_token';
refreshToken.clientId = environment.appSettings.clientId;
return this.apiHelper.httpPost(url, refreshToken, null)
.map
(
response => {
this.setToken(response.data, refreshToken.email);
return this.getToken();
}
).catch(error => {
return Observable.throw('Please insert credentials');
});
}
}
它返回一个映射的 observable,我知道如果我替换了 do in...
return this.authService.refreshToken()
.do(() => {
订阅我会打破我猜的可观察链。我迷路了,我已经玩了很长时间没有解决方案。:D