简体   繁体   English

在Angular 4中刷新令牌以进行多个API调用

[英]Refresh token in Angular 4 for multiple api calls

I am trying to implement refresh token concept in my web app. 我正在尝试在我的Web应用程序中实现刷新令牌概念。

In page refresh i am calling 4 API's and when access-token expires am calling back-end to get a new access-token based on refresh-token. 在页面刷新中,我正在调用4个API,并且当访问令牌过期时,我在调用后端以基于刷新令牌获取新的访问令牌。

So in my case am able to get the new access-token but again unable to trigger the 4 API calls until unless am doing page refresh manually or reload the page from service. 因此,就我而言,能够获得新的访问令牌,但再次无法触发4个API调用,除非手动进行页面刷新或从服务中重新加载页面。 But i don't want to reload the page and want the API calls to be done without knowing the end user. 但是我不想重新加载页面并希望在不知道最终用户的情况下完成API调用。

Give some suggestion or some idea to do this. 给出一些建议或想法可以做到这一点。

You can use Angular HttpInterceptor to solve your problem. 您可以使用Angular HttpInterceptor解决您的问题。 see snippet below. 请参阅下面的代码段。

 @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); } } 

good article about this is at https://www.intertech.com/Blog/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/ 关于此的好文章位于https://www.intertech.com/Blog/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/

In this scenario better is use switchMap when you have one Observable and you need to grab something from another request and return a different Observable, you can use SwitchMap: https://blog.angular-university.io/rxjs-switchmap-operator/ 在这种情况下,最好在有一个Observable且需要从另一个请求中获取某些内容并返回另一个Observable时使用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)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM