用于多个api调用的Angular 4中的刷新令牌

用于多个api调用的Angular 4中的刷新令牌,angular,access-token,angular-services,Angular,Access Token,Angular Services,我正在尝试在我的web应用程序中实现刷新令牌的概念 在页面刷新中,我调用4个API,当访问令牌到期时,我调用后端以基于刷新令牌获取新的访问令牌 因此,在我的情况下,我能够获得新的访问令牌,但再次无法触发4个API调用,除非我手动进行页面刷新或从服务重新加载页面。但我不想重新加载页面,希望API调用在不了解最终用户的情况下完成 为此提供一些建议或想法。在这种情况下,最好使用switchMap 当您有一个可观察对象,并且需要从另一个请求中获取某些内容并返回不同的可观察对象时,您可以使用SwitchM

我正在尝试在我的web应用程序中实现刷新令牌的概念

在页面刷新中,我调用4个API,当访问令牌到期时,我调用后端以基于刷新令牌获取新的访问令牌

因此,在我的情况下,我能够获得新的访问令牌,但再次无法触发4个API调用,除非我手动进行页面刷新或从服务重新加载页面。但我不想重新加载页面,希望API调用在不了解最终用户的情况下完成


为此提供一些建议或想法。

在这种情况下,最好使用switchMap 当您有一个可观察对象,并且需要从另一个请求中获取某些内容并返回不同的可观察对象时,您可以使用SwitchMap:


您可以使用Angular HttpInterceptor来解决您的问题。请参阅下面的代码片段

@Injectable()
导出类KgRequestInterceptorService实现HttpInterceptor{
authenticationService:MyAuthenticationService;
snackbarService:KgSnackbarService
构造函数(专用注入器:注入器){}
AddBearAndHeaders(请求:HttpRequest,标记:字符串,覆盖?:布尔值):HttpRequest{
reqHeaders=reqHeaders.set(“授权”,“承载人”+令牌);
返回req.clone({headers:reqHeaders});
}
截取(req:HttpRequest,next:HttpHandler):可观察{
this.authenticationService=this.authenticationService?this.authenticationService:this.injector.get(MyAuthenticationService);
返回next.handle(this.addBearAndHeaders(req,this.authenticationService.accessToken)).pipe(
catchError((错误,cougt)=>{
if(HttpErrorResponse的错误实例){
开关((错误)。状态){
案例400:
返回此.handle400Error(error);
案例401:
返回此.handle401错误(请求,下一步);
案例403:
返回此.handle403Error(error);
违约:
返回抛出(错误);
}
}否则{
返回抛出(错误);
}
})
)
}
handle401Error(请求:HttpRequest,下一个:HttpHandler){
如果(!this.isRefreshingToken){
this.tokenSubject.next(null);
this.isRefreshingToken=true;
log(“isRefreshingToken”,this.isRefreshingToken);
//在此处重置,以便以下请求等待令牌
//从refreshToken调用返回。
this.authenticationService=this.authenticationService?this.authenticationService:this.injector.get(KgAuthenticationService);
此._位置=此._位置?此._位置:此.injector.get(位置);
返回此.authenticationService.RenewatToken()管道(
开关映射((newToken:string)=>{
如果(纽顿){
console.log(“newToken received:”,newToken);
this.tokenSubject.next(newToken);
此.authenticationService.storeRenewedToken(newToken);
返回next.handle(this.addbearandheaders(req,newToken,true));
}
//如果我们没有得到一个新的令牌,我们有麻烦,所以注销。
//返回此参数。注销();
}),
catchError(错误=>{
//如果调用“refreshToken”时出现异常,则会有坏消息,因此请注销。
//返回此参数。注销();
}),
完成(()=>{
this.isRefreshingToken=false;
log(“isRefreshingToken”,this.isRefreshingToken);
})
);
}否则{
返回此.tokenSubject.pipe(
过滤器(令牌=>令牌!=null),
以(1)为例,
开关映射(令牌=>{
log(“newtoken:,token.substr(token.length-20,token.length-1))
返回next.handle(this.addBearAndHeaders(req,token,true));
})
)
}
}
handle400Error(错误){
if(error&&error.status===400&&error.error&&error.error.error===='invalid\u grant'){
//如果我们得到一个400,并且错误消息为“invalid_grant”,则令牌不再有效,因此注销。
返回此参数。logoutUser();
}
返回抛出(错误);
}
handle403Error(错误){
如果(error.status==403){}
返回抛出(错误);
}

}
您可以在令牌更新呼叫的
子列表中调用服务。建议您是否可以共享代码示例是很容易的。您是否有一些到目前为止所做的代码?如果刷新令牌后需要处理多个请求,这将不起作用。刷新令牌后,它将处理一个请求,其他请求将不被处理。@RishabhShah由于令牌主题,它将工作。第一个请求将启动刷新过程,所有下一个请求将等待令牌可用:this.tokenSubject.pipe(filter(token=>token!=null),take(1)。。。。
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)
}