简体   繁体   English

在刷新令牌拦截器离子时捕获错误

[英]catch error while refresh token interceptor ionic

I'm using ionic 3, angular 5 and rxjs 5. I make intercepter in my app and works well with intercept all outgoing API and with add a token to the header and refresh token when the original token expired. 我使用的是ionic 3,angular 5和rxjs5。我在应用中制作了拦截器,可以很好地拦截所有传出的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");
  }


}

my refresh token function : 我的刷新令牌功能:

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)
      );
  }

except, If the refreshToken() failed, the catch() and finally() are never reach in the AuthInterceptor class!! 否则,如果refreshToken()失败,则AuthInterceptor类中的catch()和finally()永远不会到达! How to fix that!? 如何解决!! so I can't clear storage and navigate to the login page. 因此我无法清除存储并导航至登录页面。

Try this tweak. 试试这个调整。

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)
      );
}
  • ie the missing }), between return and catchError. 即缺少的}),在return和catchError之间。
  • return appears to be redundant too, so I commented out. 返回似乎也是多余的,所以我注释掉了。

Per here . 在这里

Let me know if that helps. 让我知道是否有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM