typescript Angular -等待刷新令牌功能完成后再转发请求

mm9b1k5b  于 2023-01-02  发布在  TypeScript
关注(0)|答案(1)|浏览(107)

我正在angular中使用一个auth系统,它有一个jwt的django后端,我有一个angular拦截器,它检查每个请求中的访问令牌是否仍然有效,如果无效,它调用refreshtoken函数并刷新访问令牌。
下面是拦截器的代码:

constructor(private authService:AuthService) {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    let access_token = localStorage.getItem("access_token");
    
    if(access_token){
      // Check if access token is no longer valid, if so, refresh it with the refresh token
      if(this.authService.isLoggedOut()){
        
        this.authService.refreshToken();
        access_token = localStorage.getItem("access_token");
      }
      const cloned = request.clone({
        headers: request.headers.set("Authorization", "Bearer " + access_token)
      });
      return next.handle(cloned);
    } 
    else{
      return next.handle(request);
    }

它获取access_token并在auth服务的帮助下检查有效性。我的问题是,如果它无效,它会调用refreshToken()函数,如下所示:

refreshToken(){
    let refresh_token = localStorage.getItem("refresh_token");
    console.log("BEFORE REFRESH: " + localStorage.getItem("access_token"));
 
    return this.http.post(`${apiUrl}token/refresh/`, {"refresh" : refresh_token}).subscribe(res => {
      let access_token = res["access"]
      const expiresAt = this.tokenExpiresAt(access_token);
      localStorage.setItem("access_token", access_token);
      localStorage.setItem("expires_at", JSON.stringify(expiresAt.valueOf()));

      console.log("AFTER REFRESH: " + localStorage.getItem("access_token"));
    });
  }

但它并不等待刷新令牌函数完成并返回句柄,因此第一个带有无效令牌的请求会抛出错误,只有后面的请求才是正确的。
我如何修改它以等待refreshToken()完成?
谢谢你的时间!

kr98yfug

kr98yfug1#

可以使用rxjs运算符,例如switchMap

intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    let access_token = localStorage.getItem("access_token");
    if (access_token) {
        // Check if access token is no longer valid, if so, refresh it with the refresh token
        if (this.authService.isLoggedOut()) {
            return this.authService.refreshToken().pipe(
                switchMap(token => {
                    const cloned = request.clone({
                        headers: request.headers.set("Authorization", "Bearer " + access_token)
                    });
                    return next.handle(cloned);
                })
            )
        }
    } else {
        return next.handle(request);
    }
}

refreshToken函数中-使其返回Observsble并在pipe中设置localStorage

refreshToken(){
let refresh_token = localStorage.getItem("refresh_token");
console.log("BEFORE REFRESH: " + localStorage.getItem("access_token"));

return this.http.post(`${apiUrl}token/refresh/`, {"refresh" : refresh_token}).pipe(tap(res => {
  let access_token = res["access"]
  const expiresAt = this.tokenExpiresAt(access_token);
  localStorage.setItem("access_token", access_token);
  localStorage.setItem("expires_at", JSON.stringify(expiresAt.valueOf()));

  console.log("AFTER REFRESH: " + localStorage.getItem("access_token"));
});
 )
 }

相关问题