ошибка перехвата при обновлении токена - PullRequest
0 голосов
/ 28 февраля 2019

Я использую 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 (), функции catch () и finally () никогда не достигаются в классе AuthInterceptor !!Как это исправить?поэтому я не могу очистить хранилище и перейти на страницу входа.

1 Ответ

0 голосов
/ 28 февраля 2019

Попробуйте эту настройку.

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.
  • Возврат также представляется избыточным, поэтому я прокомментировал.

За здесь .

Дайте мне знать, если это поможет.

...