Angular Auth拦截器未能刷新令牌 - Angular 7

问题描述 投票:1回答:1

如果刷新令牌过期,我尝试刷新访问令牌。在我登录后,我收到了两个令牌并将它们存储在我的本地存储中。在服务器响应状态401之后,我试图发送刷新令牌但是它失败了,似乎拦截器在头部内发送berer访问令牌而不是刷新令牌

Auth拦截器

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  private isRefreshing = false;
  private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);

  constructor(private authService: LoginService,
              private uploadService: ContractUploadService  ) { }


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

    if (this.authService.getJwtAccessToken()) {
      request = this.addToken(request, this.authService.getJwtAccessToken());
    }

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

  addToken(request: HttpRequest<any>, token: string) {
    return request.clone({
      setHeaders: {
        'Authorization': `Bearer ${token}`
      }
    });
  }

  handle401Error(request: HttpRequest<any>, next: HttpHandler) {
    if (!this.isRefreshing) {
      this.isRefreshing = true;
      this.refreshTokenSubject.next(null);

      return this.authService.refreshToken().pipe(
        finalize(() => this.isRefreshing = false),
        switchMap((token: any) => {
          if (token) {
            this.refreshTokenSubject.next(token.jwt);
            return next.handle(this.addToken(request, token.jwt));
          }
          this.authService.doLogoutUser();
          this.uploadService.stopUploadStatusChecker();
        }),
        catchError(error => {
          this.authService.doLogoutUser();
          this.uploadService.stopUploadStatusChecker();
          return throwError(error);
        })
      );
    } else {
      return this.refreshTokenSubject.pipe(
        filter(token => token != null),
        take(1),
        switchMap(jwt => {
          return next.handle(this.addToken(request, jwt));
        }));
    }
  }
}

刷新令牌请求

  refreshToken() {
    return this.http
      .post<any>(BACK_END_URL_REFRESH, {
        'refresh_token': this.getRefreshToken()
      })
      .pipe(
        tap((tokens: any) => {
          this.storeJwtToken(tokens.jwt);
          this.isAuthenticated = true;
        }),
        catchError((err: any) => {
          console.log(err)
          this.doLogoutUser();
          return throwError(err);
        })
      );
  }

登录

  login(user: UserLogin) {
    const userData = new FormData();
    userData.append('user', user.name);
    userData.append('pwd', user.password);

    this.http.post<{ access_token: string; refresh_token: string }>(BACK_END_URL, userData).pipe(
      finalize(() => this.interactionService.setSpinnerStatus.next(false)),
    )
      .subscribe(
        response => {
          if (response.access_token) {
            this.isAuthenticated = true;
            this.interactionService.setSnackBar('User logged in successfully', 'success');
            this.storeTokens(response.refresh_token, response.access_token);
            this.extractUserInfoFromToken(response.access_token);
            this.router.navigate(['/user-panel']);
          }
        },
        error => {
          this.interactionService.setSnackBar('Wrong user name or password', 'error');
        }
      );
  }

本地存储方法

  private getRefreshToken() {
    return localStorage.getItem(this.REFRESH_TOKEN);
  }

  private storeJwtToken(jwt: string) {
    localStorage.setItem(this.JWT_ACCESS_TOKEN, jwt);
  }

  private storeTokens(refreshToken, accessToken) {
    localStorage.setItem(this.REFRESH_TOKEN, refreshToken);
    localStorage.setItem(this.JWT_ACCESS_TOKEN, accessToken);
  }

  private removeTokens() {
    localStorage.removeItem(this.JWT_ACCESS_TOKEN);
    localStorage.removeItem(this.REFRESH_TOKEN);
  }

[编辑]试图实施@Abdellah ASKI建议,但它仍然无法正常工作

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

    if (this.authService.getJwtAccessToken() && request.headers.get('No-Auth') !== 'true') {
      request = this.addToken(request, this.authService.getJwtAccessToken());
    }

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

 refreshToken() {
    return this.http
      .post<any>(BACK_END_URL_REFRESH, {
        refresh_token: this.getRefreshToken(),
        'No-Auth': 'true'
      })
      .pipe(
          tap((tokens: any) => {
            this.storeJwtToken(tokens.jwt);
            this.isAuthenticated = true;
          }),
            catchError((err: any) => {
              this.doLogoutUser();
              return throwError(err);
            })
      );

[Aaditi]

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

    if (this.authService.getJwtAccessToken() && !request.headers.has('No-Auth')) {
      request = this.addToken(request, this.authService.getJwtAccessToken());
    }

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

  addToken(request: HttpRequest<any>, token: string) {
    return request.clone({
      setHeaders: {
        'Authorization': `Bearer ${token}`
      }
    });
  }

Headers

angular
1个回答
0
投票

[更新]

解决此问题的想法是在每个请求上添加一个名为No-Auth:true的头,而不是发送访问令牌的请求。

所以在你的代码中你需要这样做:

在你的refreshToken()函数中,你需要添加一个像这样的新标题:

refreshToken() {
    return this.http
      .post<any>(BACK_END_URL_REFRESH, {
        'refresh_token': this.getRefreshToken(),
        'No-Auth': 'true' <<-------<<-------<<-------<<-------
      })
      .pipe(
        ....
      );
  }

在您的Auth拦截器上,如果存在,则需要检查此标头,您不需要添加访问令牌:

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
    if (request.headers.has('No-Auth')) { <<-------<<-------<<-------
        return next.handle(request);
    }

    if (this.authService.getJwtAccessToken()) {
      request = this.addToken(request, this.authService.getJwtAccessToken());
    }

    ....
  }
© www.soinside.com 2019 - 2024. All rights reserved.