HttpInterceptor在Angular 9中用于jwt令牌刷新的问题

HttpInterceptor在Angular 9中用于jwt令牌刷新的问题,angular,rxjs,jwt,angular-httpclient,angular-http-interceptors,Angular,Rxjs,Jwt,Angular Httpclient,Angular Http Interceptors,我正在使用jwt进行身份验证。我在提神方面有困难。可能我认为这是因为我在rxjs观测值和操作符方面缺乏经验。我使用auth.service.ts的这些方法从后端获取刷新令牌 @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private authService: AuthService) {} intercept(request: HttpRequest<an

我正在使用jwt进行身份验证。我在提神方面有困难。可能我认为这是因为我在rxjs观测值和操作符方面缺乏经验。我使用auth.service.ts的这些方法从后端获取刷新令牌

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private authService: AuthService) {}

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

    if (this.authService.hasValidToken()) {
      request = this.addAuthenticationToken(request);
    } 

    return next.handle(request).pipe(
      catchError(error => {
        if (error instanceof HttpErrorResponse && error.status === 401) {
          return this.handle401Error(request, next);
        } else {
           throw error;
        }
      }));
  } 

  handle401Error(request: HttpRequest<any>, next: HttpHandler) {
    return this.authService.getNewAccessToken().pipe(
      switchMap((response: Token) => {
        return next.handle(this.addAuthenticationToken(request));
      })
    )
  }

  addAuthenticationToken(request: HttpRequest<any>) {
    const authToken = this.authService.getAuthToken();
    return request.clone({
      setHeaders: {
       'Authorization': `Bearer ${authToken}` 
      }
    });
  }

}
getNewAccessToken(refreshToken:string){
返回此.httpClient.post(`${this.baseService.baseUrl}auth-token-refresh/`,{refresh:refreshttoken},this.baseService.httpOptions)。管道(
映射((响应:令牌)=>{
this.cookieService.set(environment.tokenAccessName,response.access,null,“/”,null,null,'Strict');
返回响应;
}
));
}
getAuthToken(){
返回this.cookieService.get(this.tokenAccessName);
}
getRefreshToken(){
返回this.cookieService.get(this.tokenRefreshName);
}
hasValidToken(){
if(this.getAuthToken())
return!helper.isTokenExpired(this.getAuthToken());
其他的
返回false;
}
这是我的拦截器auth interceptor.ts

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private authService: AuthService) {}

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

    if (this.authService.hasValidToken()) {
      request = this.addAuthenticationToken(request);
    } 

    return next.handle(request).pipe(
      catchError(error => {
        if (error instanceof HttpErrorResponse && error.status === 401) {
          return this.handle401Error(request, next);
        } else {
           throw error;
        }
      }));
  } 

  handle401Error(request: HttpRequest<any>, next: HttpHandler) {
    return this.authService.getNewAccessToken().pipe(
      switchMap((response: Token) => {
        return next.handle(this.addAuthenticationToken(request));
      })
    )
  }

  addAuthenticationToken(request: HttpRequest<any>) {
    const authToken = this.authService.getAuthToken();
    return request.clone({
      setHeaders: {
       'Authorization': `Bearer ${authToken}` 
      }
    });
  }

}
从'@angular/core'导入{Injectable};
进口{
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor,
HttpErrorResponse
}来自“@angular/common/http”;
从“../services/auth.service”导入{AuthService};
从“rxjs”导入{throwError};
从“rxjs/operators”导入{catchError,map};
从“../models/Token”导入{Token};
@可注射()
导出类AuthInterceptor实现HttpInterceptor{
构造函数(私有authService:authService){}
拦截(请求:HttpRequest,下一步:HttpHandler){
const authToken=this.authService.getAuthToken();
如果(authToken){
if(this.authService.hasValidToken()){
请求=此.addAuthenticationToken(请求);
} 
} 
返回next.handle(request).pipe(catchError)(error=>{
if(HttpErrorResponse的错误实例&&error.status==401){
返回此.handle401错误(请求,下一步);
}否则{
返回投掷器(错误);
}
}));
}
handle401Error(请求:HttpRequest,下一个:HttpHandler){
const refreshttoken=this.authService.getRefreshtToken();
this.authService.getNewAccessToken(refreshToken).subscribe(
(响应:令牌)=>{
此.addAuthenticationToken(请求);
下一步返回。处理(请求);
},
错误=>throwError(错误)
)
}
addAuthenticationToken(请求:HttpRequest){
const authToken=this.authService.getAuthToken();
return request.clone({
headers:request.headers.set('Authorization','Bearer'+authToken),
});
}
}
我的ide显示以下错误

Property 'intercept' in type 'AuthInterceptor' is not assignable to the same property in base type 'HttpInterceptor'.
Type '(request: HttpRequest<any>, next: HttpHandler) => Observable<unknown>' is not assignable to type '(req: HttpRequest<any>, next: HttpHandler) => Observable<HttpEvent<any>>'.
Type 'Observable<unknown>' is not assignable to type 'Observable<HttpEvent<any>>'.
Type 'unknown' is not assignable to type 'HttpEvent<any>'.
Property 'type' is missing in type '{}' but required in type 'HttpUserEvent<any>'.
类型“AuthInterceptor”中的属性“intercept”不能分配给基类型“HttpInterceptor”中的相同属性。 类型'(请求:HttpRequest,下一个:HttpHandler)=>Observable'不可分配给类型'(请求:HttpRequest,下一个:HttpHandler)=>Observable'。 类型“Observable”不可分配给类型“Observable”。 类型“未知”不可分配给类型“HttpEvent”。 类型“{}”中缺少属性“type”,但类型“HttpUserEvent”中需要属性“type”。 而且

Argument of type '(error: any) => void | Observable<never>' is not assignable to parameter of type '(err: any, caught: Observable<HttpEvent<any>>) => ObservableInput<any>'.
Type 'void | Observable<never>' is not assignable to type 'ObservableInput<any>'.
Type 'void' is not assignable to type 'ObservableInput<any>'.
类型为“(error:any)=>void | Observable”的参数不能分配给类型为“(err:any,capture:Observable)=>ObservableInput”的参数。 类型“void | Observable”不可分配给类型“ObservableInput”。 类型“void”不可分配给类型“ObservableInput”。
我想我可能弄错了返回类型,但我不知道出了什么问题,我终于找到了解决办法。不管怎样,也许有人可以尝试改进它 我做了以下更改,现在它可以工作了 将Observable>添加到截取签名会导致我问题中解释的第一个问题消失。对于第二个问题,我遵循问题评论中的建议。 拦截器类

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private authService: AuthService) {}

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

    if (this.authService.hasValidToken()) {
      request = this.addAuthenticationToken(request);
    } 

    return next.handle(request).pipe(
      catchError(error => {
        if (error instanceof HttpErrorResponse && error.status === 401) {
          return this.handle401Error(request, next);
        } else {
           throw error;
        }
      }));
  } 

  handle401Error(request: HttpRequest<any>, next: HttpHandler) {
    return this.authService.getNewAccessToken().pipe(
      switchMap((response: Token) => {
        return next.handle(this.addAuthenticationToken(request));
      })
    )
  }

  addAuthenticationToken(request: HttpRequest<any>) {
    const authToken = this.authService.getAuthToken();
    return request.clone({
      setHeaders: {
       'Authorization': `Bearer ${authToken}` 
      }
    });
  }

}
@Injectable()
导出类AuthInterceptor实现HttpInterceptor{
构造函数(私有authService:authService){}
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
if(this.authService.hasValidToken()){
请求=此.addAuthenticationToken(请求);
} 
返回next.handle(request.pipe)(
catchError(错误=>{
if(HttpErrorResponse的错误实例&&error.status==401){
返回此.handle401错误(请求,下一步);
}否则{
投掷误差;
}
}));
} 
handle401Error(请求:HttpRequest,下一个:HttpHandler){
返回此.authService.getNewAccessToken()管道(
开关映射((响应:令牌)=>{
返回next.handle(this.addAuthenticationToken(请求));
})
)
}
addAuthenticationToken(请求:HttpRequest){
const authToken=this.authService.getAuthToken();
return request.clone({
集合标题:{
'Authorization':`Bearer${authToken}`
}
});
}
}
而我的身份验证服务中获取刷新令牌的功能已修改为

getNewAccessToken(){
    return this.httpClient.post<Token>(`${this.baseService.baseUrl}auth-token-refresh/`, { refresh: this.getRefreshToken() }, this.baseService.httpOptions).pipe(
      tap((response:Token) => {
        this.cookieService.set(environment.tokenAccessName, response.access, null, '/', null, null, 'Strict');
      }
    ));
  }
getNewAccessToken(){
返回此.httpClient.post(`${this.baseService.baseUrl}auth-token-refresh/`,{refresh:this.getrefreshttoken()},this.baseService.httpOptions)。管道(
点击((响应:令牌)=>{
this.cookieService.set(environment.tokenAccessName,response.access,null,“/”,null,null,'Strict');
}
));
}

我们可以获得您的身份验证拦截器的内容吗?@htn谢谢,我没有注意到我粘贴了错误的代码。我理解您的意图。很容易找到错误:handle401Error应该返回一个可观察的
(此处无效)。第一个
返回投掷错误
应替换为
投掷错误。对于第二个,不要在subscribe的errorHandler中返回任何内容。然而,要给你一个正确的答案并不容易