Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 6 HTTP侦听器刷新令牌401处理_Angular_Typescript_Angular Http Interceptors - Fatal编程技术网

Angular 6 HTTP侦听器刷新令牌401处理

Angular 6 HTTP侦听器刷新令牌401处理,angular,typescript,angular-http-interceptors,Angular,Typescript,Angular Http Interceptors,我已经构建了AuthInterceptor,它根据401错误发送请求以获取新令牌 遇到401错误时会调用handle401Error方法,但在this.authService.refreshToken().pipe()中似乎没有收到任何响应 AuthInterceptor import { Injectable, Injector } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEve

我已经构建了AuthInterceptor,它根据401错误发送请求以获取新令牌

遇到401错误时会调用handle401Error方法,但在this.authService.refreshToken().pipe()中似乎没有收到任何响应

AuthInterceptor

import { Injectable, Injector } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, tap, switchMap } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  isRefreshingToken:boolean = false;
  constructor(public authService: AuthService, private injector: Injector) {}

    addToken(req: HttpRequest<any>, token: string): HttpRequest<any> {
        return req.clone({ setHeaders: {
          Authorization: 'Bearer ' + token,
          'Content-Type': 'application/json'
       }})
    }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    request = this.addToken(request, this.authService.getToken())
    return next.handle(request).pipe (
      catchError((error: Error) => {
        if(error instanceof HttpErrorResponse){
          console.log('err', error);
          switch(error.status) {
            case 401:
            this.handle401Error(request, next)
            default:
            return throwError(error);
          }

        } else {
          return throwError(error);
        }
      })
    );
  }

  handle401Error(request: HttpRequest<any>, next: HttpHandler){
    console.log('handle 401');
    if(!this.isRefreshingToken) { //do not send another refresh token request if already in progress
      this.isRefreshingToken = true;

      return this.authService.refreshToken().pipe(
        switchMap((newToken: string) => {
          console.log('newToken', newToken) // I DO NOT GET A VALUE HERE
            if (newToken) { 
              return next.handle(this.addToken(request, newToken));
            }

        }),
        catchError((error) => {
          console.log('error', error) //NOR DO I GET AN ERROR
          return throwError(error)
        }),
        tap(data => console.log(data))
      )
    }
  }
}
从'@angular/core'导入{Injectable,Injector};
从'@angular/common/http'导入{HttpInterceptor,HttpRequest,HttpHandler,HttpEvent,HttpErrorResponse};
从“rxjs”导入{observatable,throwerr};
从“rxjs/operators”导入{catchError,tap,switchMap};
从“../services/auth.service”导入{AuthService};
@可注射()
导出类AuthInterceptor实现HttpInterceptor{
isRefreshingToken:boolean=false;
构造函数(公共authService:authService,私有注入器:注入器){}
addToken(请求:HttpRequest,标记:string):HttpRequest{
返回请求克隆({setHeaders:{
授权:“持票人”+代币,
“内容类型”:“应用程序/json”
}})
}
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
request=this.addToken(request,this.authService.getToken())
返回next.handle(request.pipe)(
catchError((错误:error)=>{
if(HttpErrorResponse的错误实例){
console.log('err',error);
开关(错误状态){
案例401:
此.handle401错误(请求,下一个)
违约:
返回投掷器(错误);
}
}否则{
返回投掷器(错误);
}
})
);
}
handle401Error(请求:HttpRequest,下一个:HttpHandler){
log('handle401');
如果(!this.isRefreshingToken){//如果已在进行刷新令牌请求,则不要发送另一个刷新令牌请求
this.isRefreshingToken=true;
返回此.authService.refreshToken()管道(
开关映射((newToken:string)=>{
log('newToken',newToken)//我在这里没有得到值
如果(newToken){
返回next.handle(this.addToken(request,newToken));
}
}),
catchError((错误)=>{
console.log('error',error)//我也没有收到错误
返回投掷器(错误)
}),
点击(数据=>console.log(数据))
)
}
}
}
AuthService刷新令牌

refreshToken(): Observable<string> {
    console.log('refreshToken');
    let token = 'xxx-xxx-xx';

    return of(token).pipe(delay(1000));
}
refreshToken():可观察{
log('refreshToken');
let token='xxx xxx xx';
返回(令牌)管道(延迟(1000));
}

除了“案例401”中缺少的报税表之外,下面是我将如何处理它

基本思想是,您希望在收到新的刷新令牌后重试整个observable。此外,请求在一个可观察的内部进行修补,以便在每次重试时,它将从身份验证服务获得新的令牌

import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';

import { Observable } from 'rxjs';
import { catchError, retryWhen, switchMap, tap } from 'rxjs/operators';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  private retryRequest = Symbol('reload');
  private refreshToken = this.authService.refreshToken()
    .pipe(
      tap(newToken => {
        if (newToken) {
          throw this.retryRequest;
        }
      }),
      share(),
    ) as Observable<any>;

  constructor(public authService: AuthService) { }

  private addToken(req: HttpRequest<any>, token: string): HttpRequest<any> {
    return req.clone({
      setHeaders: {
        Authorization: 'Bearer ' + token,
        'Content-Type': 'application/json'
      }
    });
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const request$ = new Observable<HttpRequest<any>>(observer => {
      observer.next(this.addToken(request, this.authService.getToken()));
      observer.complete();
    });

    return request$.pipe(
      switchMap(req => next.handle(req)),
      catchError((error: Error) => {
        if (error instanceof HttpErrorResponse) {
          switch (error.status) {
            case 401:
              return this.refreshToken;
            default:
              throw error;
          }
        } else {
          throw error;
        }
      }),
      retryWhen(err$ =>
        err$.pipe(
          tap(err => {
            if (err === this.retryRequest) { return; }
            throw err;
          })
        )
      )
    );
  }
}
从'@angular/common/http'导入{HttpErrorResponse,HttpEvent,HttpHandler,HttpInterceptor,HttpRequest};
从“@angular/core”导入{Injectable};
从“rxjs”导入{Observable};
从“rxjs/operators”导入{catchError、retryWhen、switchMap、tap};
@可注射()
导出类AuthInterceptor实现HttpInterceptor{
private retryRequest=Symbol('reload');
private refreshToken=this.authService.refreshToken()
.烟斗(
点击(newToken=>{
如果(纽顿){
抛出这个.retryRequest;
}
}),
share(),
)可观察的;
构造函数(公共authService:authService){}
私有addToken(req:HttpRequest,token:string):HttpRequest{
返回请求克隆({
集合标题:{
授权:“持票人”+代币,
“内容类型”:“应用程序/json”
}
});
}
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
const request$=新的可观察对象(观察者=>{
next(this.addToken(request,this.authService.getToken());
observer.complete();
});
返回请求$.pipe(
开关映射(req=>next.handle(req)),
catchError((错误:error)=>{
if(HttpErrorResponse的错误实例){
开关(错误状态){
案例401:
返回此.refreshToken;
违约:
投掷误差;
}
}否则{
投掷误差;
}
}),
retryWhen(err$=>
err$.pipe(
轻触(错误=>{
如果(err==this.retryRequest){return;}
犯错误;
})
)
)
);
}
}

案例401
中,您需要
返回此。处理401错误(请求,下一步)
。此外,如果
isRefreshingToken
为真,会发生什么。你不想在刷新令牌后再次重试请求吗?难以置信,不知道我怎么会错过返回语句。如果refreshToken为true,Yes将处理该条件。非常感谢你指出这一点out@Neil你解决问题了吗?同样的事情也发生在你身上me@usmansaleem你具体面临什么问题?你有一个堆栈闪电战样本吗?