【问题标题】:catch error while refresh token interceptor ionic刷新令牌拦截器离子时捕获错误
【发布时间】:2019-02-28 15:25:48
【问题描述】:

我正在使用 ionic 3、angular 5 和 rxjs 5。 我在我的应用程序中制作了拦截器,并且可以很好地拦截所有传出 API,并在原始令牌过期时向标头添加令牌并刷新令牌。

import {Observable, BehaviorSubject} from 'rxjs';
import {_throw} from "rxjs/observable/throw";

import {take, filter, catchError, switchMap, finalize} from 'rxjs/operators';
import {Injectable, Injector} from "@angular/core";
import {HttpInterceptor, HttpRequest, HttpHandler, HttpSentEvent, HttpHeaderResponse, HttpProgressEvent,
  HttpResponse, HttpUserEvent, HttpErrorResponse} from "@angular/common/http";

import {ResetApiProvider} from "../providers/reset-api/reset-api";
import {Events} from "ionic-angular";

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  isRefreshingToken: boolean = false;
  tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);

  constructor(private injector: Injector, public event: Events) {}

  addToken(req: HttpRequest<any>, token: string): HttpRequest<any> {
    return req.clone({setHeaders: {Authorization: 'Bearer ' + token}})
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
    const authService = this.injector.get(ResetApiProvider);

    return next.handle(this.addToken(req, authService.getAuthToken())).pipe(
      catchError(error => {
        if (error instanceof HttpErrorResponse) {
          switch ((<HttpErrorResponse>error).status) {
            case 400:
              return this.handle400Error(error);
            case 401:
              return this.handle401Error(req, next);
            default:
              return _throw(error);
          }
        } else {
          return _throw(error);
        }
      }));
  }

  //maybe use later for blacklist tokens
  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);
  }

  handle401Error(req: HttpRequest<any>, next: HttpHandler) {
    if (!this.isRefreshingToken) {
      this.isRefreshingToken = true;

      // Reset here so that the following requests wait until the token
      // comes back from the refreshToken call.
      this.tokenSubject.next(null);

      const authService = this.injector.get(ResetApiProvider);

      return authService.refreshToken().pipe(
        switchMap((newToken: string) => {
          console.log('bbbbbbb');
          if (newToken) {
            this.tokenSubject.next(newToken);
            return next.handle(this.addToken(req, newToken));
          }
          console.log('qqqq');

          // If we don't get a new token, we are in trouble so logout.
          return this.logoutUser();
        }),
        catchError(error => {
          // If there is an exception calling 'refreshToken', bad news so logout.
          return this.logoutUser();
        }),
        finalize(() => {
          this.isRefreshingToken = false;
        }),);
    } else {
      return this.tokenSubject.pipe(
        filter(token => token != null),
        take(1),
        switchMap(token => {
          return next.handle(this.addToken(req, token));
        }),);
    }
  }

  logoutUser() {
    const authService = this.injector.get(ResetApiProvider);
    authService.logout();
    this.event.publish('UNAUTHORIZED');
    return _throw("please login");
  }


}

我的刷新令牌功能:

public refreshToken(): Observable<string> {
    const url = `${apiUrl}/auth/refresh`;
    console.log('fffff');
    return this.http.post(url, {token: this.getAuthToken()},httpOptions)
      .pipe(
        map((res) => {
          let token: any = res;
          this.storage.set('token', token.data);
          console.log(token.data);
          this.currentToken = token.data;
           return  token.data;
        catchError(this.handleError)
      );
  }

除了,如果 refreshToken() 失败,则在 AuthInterceptor 类中永远无法到达 catch() 和 finally() !如何解决这个问题!? 所以我无法清除存储并导航到登录页面。

【问题讨论】:

    标签: javascript angular rxjs ionic3 interceptor


    【解决方案1】:

    试试这个调整。

    public refreshToken(): Observable<string> {
        const url = `${apiUrl}/auth/refresh`;
        console.log('fffff');
        return this.http.post(url, {token: this.getAuthToken()},httpOptions)
          .pipe(
            map((res) => {
              let token: any = res;
              this.storage.set('token', token.data);
              console.log(token.data);
              this.currentToken = token.data;
              //return  token.data;
            }),
            catchError(this.handleError)
          );
    }
    
    • 即return 和 catchError 之间缺少的 }),
    • return 似乎也是多余的,所以我注释掉了。

    每个here

    如果有帮助,请告诉我。

    【讨论】:

    • 抱歉,仍然无法处理捕获错误表单刷新令牌并成功如何返回新令牌?感谢您的帮助。
    猜你喜欢
    • 2020-05-12
    • 2019-07-09
    • 1970-01-01
    • 2017-02-25
    • 2020-02-10
    • 2021-05-17
    • 2017-12-31
    • 2023-03-23
    • 2017-12-26
    相关资源
    最近更新 更多