401没有捕获刷新令牌失败事件

时间:2017-12-25 07:25:11

标签: angular typescript

验证服务未注销刷新令牌401错误。而是去catchError.ts。应用程序如何处理这个问题。

方案 1.最初使用Basic Authorization标头获取访问令牌。 2.使用访问令牌进行服务器调用。 3.访问toekn过期后,请调用刷新令牌服务。 4.在刷新令牌调用成功时,使用新令牌进行其余的服务调用。 5.在刷新toeken失败时,将返回401错误,但应用程序无法捕获错误并且永远无法注销。

使用Angular 4 Http拦截器

这是拦截器

import { Injectable, Injector } from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse, HttpErrorResponse, HttpClient} from '@angular/common/http';
import * as AppUtils from '../common/app.utils';
import { AuthService } from './auth.service';
import {Observable} from 'rxjs/Rx';
import { 
    Router,
    Event, 
    NavigationStart, RoutesRecognized, NavigationEnd, NavigationCancel, NavigationError
} from '@angular/router'
import { LoaderService } from '../loader/loader.service'
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
import { EmptyObservable } from 'rxjs/observable/EmptyObservable';
import { catchError, filter, take, switchMap, finalize } from "rxjs/operators";
import { SharedService } from '../common/services/shared.service';

declare var swal: any;

@Injectable()
export class TokenInterceptor implements HttpInterceptor {

 isRefreshingToken: boolean = true;
 tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);
 constructor(private inj: Injector, private router: Router) {}

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
     const auth = this.inj.get(AuthService)  
       return next.handle(this.addToken(request))
      .pipe(
      catchError((error, ca) => {
        if (error instanceof HttpErrorResponse) {
          switch ((<HttpErrorResponse>error).status) {
            case 401:
              return this.handle401Error(request, next, auth)
            default:
              return ErrorObservable.create(error);
          }
        } else {
          return ErrorObservable.create(error);
        }
      })
      )
  }

addToken(req: HttpRequest<any>): HttpRequest<any> {

    let customReq: any;
    let client_id = 'test'; 
    let client_secret= 'secret';
    let basicheader = btoa(client_id +':'+ client_secret);
    if(req.url.indexOf("token?grant_type") < 0 || req.url.indexOf("token?grant_type") == 0){
            customReq = req.clone({
                headers: req.headers.set('Content-Type', 'application/json')
                                    .set('Authorization','Bearer '+ localStorage.getItem(AppUtils.STORAGE_ACCOUNT_ACCESS_TOKEN))
            })
                //Set estCode and perscode for Alshif Users
                if(localStorage.getItem(AppUtils.ALSHIFA_TRUSTED_LOGIN)!=null && localStorage.getItem(AppUtils.ALSHIFA_TRUSTED_LOGIN)==="Y"){
                    req.headers.append(AppUtils.ALSHIFA_USER_INFO, localStorage.getItem(AppUtils.DEFAULT_INSTITUTE) +":"+
                    localStorage.getItem(AppUtils.PERSON_CODE));
                }

      }else{
        customReq = req.clone({
          headers: req.headers.set('Authorization','Basic '+ basicheader)
      })
      }
        return customReq;

    }

     handle400Error(error) {
         console.log("400 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 EmptyObservable.create();
    }


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


    let customReq: any;
    let client_id = 'test'; 
    let client_secret= 'secret';
    let basicheader = btoa(client_id +':'+ client_secret);
    auth.refreshToken().subscribe((token) => {

                    console.log("token " +JSON.stringify(token));
                    if (token instanceof HttpErrorResponse) {
      if (token.status === 401) {
console.log("error");
      }
                    }
                    if (token) {
                        localStorage.setItem(AppUtils.STORAGE_ACCOUNT_ACCESS_TOKEN, token["access_token"]);
                        localStorage.setItem(AppUtils.STORAGE_ACCOUNT_REFRESH_TOKEN, token["refresh_token"]);
                        localStorage.setItem(AppUtils.STORAGE_ACCOUNT_EXPIRES_IN, token["expires_in"]);
                        this.tokenSubject.next(token["access_token"]);
                        return next.handle(this.addToken(req));
                    }

                    console.log("refresh failed");
                    // If we don't get a new token, we are in trouble so logout.
                     this.logoutUser();
                     return EmptyObservable.create();

              }, (err) => {
                    console.log("error  2" +err);
                    // If there is an exception calling 'refreshToken', bad news so logout.
                     this.logoutUser();
                      return EmptyObservable.create();
              },() => { 
                    console.log("token finally)");
                    this.isRefreshingToken = true;
                });

              //  )
        } else {
            console.log("this.tokenSubject "+ this.tokenSubject);
            console.log("this.tokenSubjec2 "+ this.tokenSubject.filter(token => token != null));
            return this.tokenSubject
                .filter(token => token != null)
                .take(1)
                .switchMap(token => {
                    return next.handle(this.addToken(req));
                });


        }

    }



 logoutUser(){
     swal({
            title: 'Session Expired',
            text: 'your session has been expired please re login',

            timer: 5000,
            onOpen: () => {
              swal.showLoading()
            }
          }).then((result) => {
            if (result.dismiss === 'timer') {
              this.router.navigate([AppUtils.BACKEND_API_AUTHENTICATE_PATH]);
              window.location.reload();
            }
          })
   localStorage.clear();
   this.router.navigate([AppUtils.BACKEND_API_AUTHENTICATE_PATH]);
  // window.location.reload();
   //return Observable.throw("");
 }

这是auth服务类

 import { Injectable, Component, EventEmitter } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpClient, HttpResponse, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import 'rxjs/add/operator/map';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/retry';
import * as AppUtils from '../common/app.utils';
import { Router } from '@angular/router';
import { SharedService } from '../common/services/shared.service';
import 'rxjs/add/operator/catch';

declare var swal: any;

@Injectable()
export class AuthService {

  cachedRequests: Array<HttpRequest<any>> = [];

  constructor(private router: Router, private http : HttpClient) {

  }

  refreshToken(): Observable<any>{

    let client_id = 'irsauth'; 
    let client_secret= 'secret';
    let basicheader = btoa(client_id +':'+ client_secret);
    let headers = new HttpHeaders();
    headers.set('Authorization', 'Basic ' + basicheader);
    return this.http.get(AppUtils.REFRESH_TOKEN + localStorage.getItem(AppUtils.STORAGE_ACCOUNT_REFRESH_TOKEN), { headers: headers })
    .catch((e: any) => Observable.throw(this.errorHandler(e)))


  }

 errorHandler(error: any): void {
   console.log("auth error")
   Observable.throw("");

  }


 logoutUser(){
       localStorage.clear();
   this.router.navigate([AppUtils.BACKEND_API_AUTHENTICATE_PATH]);
  // window.location.reload();
   //return Observable.throw("");
 }
}


}

1 个答案:

答案 0 :(得分:0)

这对我有用。检查这是否有帮助。基本上它是Angular Http服务的包装器。

callHttpGet(url: string) {
  let headers = new Headers({ 
          "Content-Type": "application/json", 
          "Authorization": "Bearer " + 
          localStorage.getItem("accessToken") 
  });
  let options = new RequestOptions({ headers: headers });

  var me = this;
  return this.http.get(url, options)
    .catch(initialError => {
      if (initialError && 
            initialError.status === 401 && 
            initialError.json()["message"] === "Token expired") {
        // token might be expired, try to refresh token
        var tokenObject = new Object();
        tokenObject["token"] = localStorage.getItem("refreshToken");
        return me.authenticatorService.authenticate(tokenObject)
          .flatMap(res => {
            return me.http.get(url, me.options);
          })
          .catch(error => {
            if (error && 
                    error.status === 401 && 
                    (error.json()["message"] === "Refresh token expired" || 
                    error.json()["message"] === "Token expired")) {
              localStorage.clear();
              this.router.navigate(['/login']);
              return Observable.throw(error);
            }
            else {
              return Observable.throw(error);
            }
          });
      }
      else {
        return Observable.throw(initialError);
      }
    });
}