我已经实现了令牌保存,检索和我也有刷新调用的逻辑。问题是,当我在我的HttpInterceptor中拦截403时,同时进行的其他调用也会刷新令牌。在我的令牌刷新之前,我很想接听这些电话。创建我称之为“信号量”的请求。
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
private auth: AuthService;
constructor(private injector: Injector) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.auth = this.injector.get(AuthService);
if(this.auth.isAuthenticated()){
request = request.clone({
setHeaders: {
Accept: 'application/json',
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
});
} else {
request = request.clone({
setHeaders: {
Accept: 'application/json'
}
});
}
return next.handle(request).catch(error => {
if (error.status === 401) {
console.log('refreshing token');
// TODO: return Refresh Token here and hold other calls
}
return Observable.throw(error);
});
}
答案 0 :(得分:5)
好吧,我无法设置环境来测试这个逻辑是否正常工作,但我尽了最大努力:
你的拦截器应该是这样的:
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
private auth: AuthService;
constructor(private injector: Injector) {
this.auth = this.injector.get(AuthService);
}
setHeaders(request) {
return function (token) {
return request.clone({
setHeaders: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
}
});
}
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.auth
.getToken()
.map(this.setHeaders(request))
.mergeMap(next.handle)
.catch(error => {
if (error.status === 401) {
return this.auth.refreshToken()
.map(this.setHeaders(request))
.mergeMap(next.handle);
}
return Observable.throw(error);
});
}
}
您的AuthService:
@Injectable()
export class AuthService {
private refreshTokenCall;
saveTokenInLocalStorage(token) {
localStorage.setItem('access_token', token);
}
getToken() {
if (localStorage.getItem('access_token')) {
return Observable.of(localStorage.getItem('access_token'));
}
return this.refreshToken();
}
refreshToken() {
if (!this.refreshTokenCall) {
this.refreshTokenCall = this.http.get(refreshTokenURL)
// Maybe a .map() here, it depends how the backend returns the token
.do(this.saveTokenInLocalStorage)
.finally(() => this.refreshTokenCall = null);
}
return this.refreshTokenCall;
}
}
我希望它能以某种方式帮助你。