簡體   English   中英

angular 2 http異常處理程序和jwt刷新

[英]angular 2 http exception handler and jwt refresh

當遇到某個異常時,我正在嘗試刷新JWT令牌,當它是另一個異常時,我的ErrorHandler應該處理它們。

我有一段代碼,其中一個代碼可用於令牌刷新,而另一段代碼可用於異常處理程序,但我只是無法以一種有效的方式組合它們。

問題是我無法拋出異常並以可觀察的方式用我的ErrorHandler捕獲它。

這是我可以用來刷新令牌的代碼。 如果失敗,它將檢查錯誤代碼是否為token_expired ,如果失敗,它將刷新令牌token_expired試請求。

export class HttpErrorService extends Http {

  constructor(backend: XHRBackend, defaultOptions: RequestOptions) {
    super(backend, defaultOptions);
  }

  request(url: string | Request, options?: RequestOptionsArgs, disableRefresh = false): Observable<Response> {
      return super.request(url, options).catch((error: Response) => {
        // Refresh token on token_expired exception.
        if (!disableRefresh && error.status === 401 && error.json().error.code === 'token_expired') {
          return this.renewToken().flatMap((response) => {
            const res = response.json();
            // Replace the token in storage.
            localStorage.setItem('__token', res.data.token);

            // Replace request the token with the new one.
            if (url instanceof Request) {
              url.headers.set('Authorization', 'Bearer ' + res.data.token);
            } else if (options) {
              options.headers.set('Authorization', 'Bearer ' + res.data.token);
            }

            // To prevent a loop disable refreshing at the next request.
            return this.request(url, options, true);
          });
        }

        // Here I want to throw the exception.
        // I need to be able to catch it with my exception handler.
        // throw error; doesn't work.
        return Observable.throw(error);
      });
  }

  private getBaseUrl(): string {
    return environment.base_uri;
  };

  renewToken(): Observable<Response> {
    const headers = new Headers();
    headers.append('Authorization', 'Bearer ' + localStorage.getItem('__token'))

    return this.post(this.getBaseUrl() + '/auth/refresh', {}, {headers: headers});
  }
}

上面唯一的壞處是我無法在異常處理程序中捕獲異常。

以下代碼可以引發ErrorHandler可以捕獲的異常。 但我不知道如何在一次通話中刷新令牌...

export class HttpErrorService extends Http {

  constructor(backend: XHRBackend, defaultOptions: RequestOptions) {
    super(backend, defaultOptions);
  }

  request(url: string | Request, options?: RequestOptionsArgs, disableRefresh = false): Observable<Response> {
    return Observable.create(observer => {
      super.request(url, options).subscribe(
        res => observer.next(res),
        err => {
          if (!disableRefresh && err.status === 401 && err.json().error.code === 'token_expired') {
            // I can't return this.renewToken()...
          }
          observer.error(err);
          throw new HttpException(err); // this is getting catched by the ErrorHandler
        },
        () => observer.complete);
    });
  }

  private getBaseUrl(): string {
    return environment.base_uri;
  };

  renewToken(): Observable<Response> {
    const headers = new Headers();
    headers.append('Authorization', 'Bearer ' + localStorage.getItem('__token'))

    return this.post(this.getBaseUrl() + '/auth/refresh', {}, {headers: headers});
  }
}

我的錯誤處理程序僅包含console.log()
https://angular.io/api/core/ErrorHandler

我該如何工作?

幾個小時后,我終於找到了解決方案!

export class HttpErrorService extends Http {

  constructor(backend: XHRBackend, defaultOptions: RequestOptions) {
    super(backend, defaultOptions);
  }

  request(url: string | Request, options?: RequestOptionsArgs, disableRefresh = false): Observable<Response> {
    return Observable.create(observer => {
      super.request(url, options).retryWhen(attempts => this.retryRequest(attempts)).catch((error: Response) => {
        // Refresh token on token_expired exception.
        if (!disableRefresh && error.status === 401 && error.json().error.code === 'token_expired') {
          return this.renewToken().flatMap((response) => {
            const res = response.json();
            // Replace the token in storage.
            localStorage.setItem('__token', res.data.token);

            // Replace request the token with the new one.
            if (url instanceof Request) {
              url.headers.set('Authorization', 'Bearer ' + res.data.token);
            } else if (options) {
              options.headers.set('Authorization', 'Bearer ' + res.data.token);
            }

            // To prevent a loop disable refreshing at the next request.
            return this.request(url, options, true);
          });
        }

        throw Observable.throw(error);
      }).subscribe(
        res => observer.next(res),
        err => {
          observer.error(err);
          throw new HttpException(err);
        }
      );
    });
  }

  private getBaseUrl(): string {
    return environment.base_uri;
  };

  renewToken(): Observable<Response> {
    const headers = new Headers();
    headers.append('Authorization', 'Bearer ' + localStorage.getItem('__token'))

    return this.post(this.getBaseUrl() + '/auth/refresh', {}, {headers: headers});
  }

  retryRequest(attempts: any) {
    let count = 0;

    return attempts.flatMap(error => {
        return ++count >= 3 ? Observable.throw(error) : Observable.timer(count * 1000);
    });
  }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM