我正在尝试在我的web应用程序中实现刷新令牌的概念。
在页面刷新中,我调用了4个API,当访问令牌过期时,我将调用后端,以获取基于刷新令牌的新访问令牌。
因此,在我的情况下,我能够获得新的访问令牌,但同样无法触发4个API调用,除非我手动执行页面刷新或从服务重新加载页面。但我不想在不知道最终用户的情况下重新加载页面和完成API调用。
给出一些建议或想法来做这件事。
发布于 2018-03-14 15:41:08
你可以使用Angular HttpInterceptor来解决你的问题。请参阅下面的代码片段。
@Injectable()
export class KgRequestInterceptorService implements HttpInterceptor {
authenticationService: MyAuthenticationService;
snackbarService: KgSnackbarService
constructor(private injector: Injector) { }
addBearerAndHeaders(req: HttpRequest<any>, token: string, overwrite?: boolean): HttpRequest<any> {
reqHeaders = reqHeaders.set("Authorization", 'Bearer ' + token);
return req.clone({ headers: reqHeaders });
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
this.authenticationService = this.authenticationService ? this.authenticationService : this.injector.get<MyAuthenticationService>(MyAuthenticationService);
return next.handle(this.addBearerAndHeaders(req, this.authenticationService.accessToken)).pipe(
catchError((error, cought) => {
if (error instanceof HttpErrorResponse) {
switch ((<HttpErrorResponse>error).status) {
case 400:
return this.handle400Error(error);
case 401:
return this.handle401Error(req, next);
case 403:
return this.handle403Error(error);
default:
return _throw(error);
}
} else {
return _throw(error);
}
})
)
}
handle401Error(req: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshingToken) {
this.tokenSubject.next(null);
this.isRefreshingToken = true;
console.log("isRefreshingToken", this.isRefreshingToken);
// Reset here so that the following requests wait until the token
// comes back from the refreshToken call.
this.authenticationService = this.authenticationService ? this.authenticationService : this.injector.get<KgAuthenticationService>(KgAuthenticationService);
this._location = this._location ? this._location : this.injector.get<Location>(Location);
return this.authenticationService.renewToken().pipe(
switchMap((newToken: string) => {
if (newToken) {
console.log("newToken Recieved:", newToken);
this.tokenSubject.next(newToken);
this.authenticationService.storeRenewedToken(newToken);
return next.handle(this.addBearerAndHeaders(req, newToken, true));
}
// If we don't get a new token, we are in trouble so logout.
//return this.logout();
}),
catchError(error => {
// If there is an exception calling 'refreshToken', bad news so logout.
//return this.logout();
}),
finalize(() => {
this.isRefreshingToken = false;
console.log("isRefreshingToken", this.isRefreshingToken);
})
);
} else {
return this.tokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(token => {
console.log("newtoken:", token.substr(token.length - 20, token.length - 1))
return next.handle(this.addBearerAndHeaders(req, token, true));
})
)
}
}
handle400Error(error) {
if (error && error.status === 400 && error.error && error.error.error === 'invalid_grant') {
// If we get a 400 and the error message is 'invalid_grant', the token is no longer valid so logout.
return this.logoutUser();
}
return _throw(error);
}
handle403Error(error) {
if (error.status === 403) { }
return _throw(error);
}
}
关于这一点的好文章在https://www.intertech.com/Blog/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/
发布于 2018-03-14 15:35:08
在此场景中,当您有一个可观察对象并且需要从另一个请求中获取某些内容并返回另一个可观察对象时,更好的方法是使用switchMap,您可以使用SwitchMap:https://blog.angular-university.io/rxjs-switchmap-operator/
ngOnInit() {
this._moviesDataService.getShowtimes()
.switchMap(res => {
const id = Object.keys(res[0].showtimes)[0]; // assuming you have one element in your array and you want the first id from showtimes
return this.getMovies(id); // assuming, you have a separate method that returns the movies
})
.subscribe(res => this.results = res)
}https://stackoverflow.com/questions/49271828
复制相似问题