【问题标题】:401 is not catching on refresh token failure event401 未捕获刷新令牌失败事件
【发布时间】:2017-12-25 21:34:21
【问题描述】:

身份验证服务未在刷新令牌时注销 401 错误。相反,它转到 catchError.ts。应用程序如何处理这个问题。

场景 1.最初使用基本授权标头获取访问令牌。 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("");
 }

这是认证服务类

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


}

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    这对我有用。检查这是否有帮助。基本上它是 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);
          }
        });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-11
      • 2015-02-22
      • 2018-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多