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

时间:2020-05-10 09:31:26

标签: angular rxjs jwt angular-httpclient angular-http-interceptors

我正在使用jwt进行身份验证。我在刷新时遇到了麻烦。我认为这可能是由于我缺乏 rxjs 可观察对象和运算符的经验所致。我使用 auth.service.ts

的这些方法从后端获取刷新令牌
    getNewAccessToken(refreshToken: string){
        return this.httpClient.post<Token>(`${this.baseService.baseUrl}auth-token-refresh/`, { refresh: refreshToken }, this.baseService.httpOptions).pipe(
          map((response:Token) => {
            this.cookieService.set(environment.tokenAccessName, response.access, null, '/', null, null, 'Strict');
            return response;
          }
        ));
      }

      getAuthToken() { 
        return this.cookieService.get(this.tokenAccessName);
      }

      getRefreshToken() { 
        return this.cookieService.get(this.tokenRefreshName);
      }

      hasValidToken() {
        if (this.getAuthToken())
          return !helper.isTokenExpired(this.getAuthToken());
        else 
          return false;
      }

这是我的拦截器 auth-interceptor.ts

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

import { AuthService } from '../services/auth.service';

import { throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { Token } from '../models/token';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private authService: AuthService) {}

  intercept(request: HttpRequest<any>, next: HttpHandler) {
    const authToken = this.authService.getAuthToken();
    if (authToken) {
      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 {
        return throwError(error);
      }
    }));
  }

  handle401Error(request: HttpRequest<any>, next: HttpHandler) {
    const refreshToken = this.authService.getRefreshToken();
    this.authService.getNewAccessToken(refreshToken).subscribe(
      (response: Token) => {
        this.addAuthenticationToken(request);
        return next.handle(request);
      },
      error => throwError(error)
    )
  }

  addAuthenticationToken(request: HttpRequest<any>) {
    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>'.

还有

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>'.

我认为我可能对返回类型有误,但我无法弄清楚出了什么问题

1 个答案:

答案 0 :(得分:0)

我终于找到了解决方案。也许有人可以尝试改善它 我进行了以下更改,现在可以使用了 在 intercept 签名中添加 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}` 
      }
    });
  }

}

身份验证服务中获得刷新令牌的功能已被修改为

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');
      }
    ));
  }
相关问题