使用拦截器的角度8刷新令牌

时间:2020-10-12 11:43:30

标签: angular jwt angular8 angular-http-interceptors

我正在尝试使用角度拦截器实现刷新令牌功能。这是我要遵循的分步程序

  1. 将访问令牌存储在本地存储中。将此令牌添加到授权标头中。

  2. 如果访问令牌已过期,请发送刷新令牌(存储在数据库中)并生成一个新令牌。

在以下代码中,我试图实现相同的功能。但是问题是当访问令牌过期时,当前的HTTP请求无法执行(给出401错误)。我必须重新加载该页面才能使该HTTP请求正常工作。如何避免这种情况?

interceptor.ts

export class HttpErrorInterceptor implements HttpInterceptor {

  
  constructor(private router: Router, private loginService: LoginService) { }
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const jwt = localStorage.getItem('token')
    if (jwt) {
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${jwt}`
        }
      });
    }
    if (!request.headers.has('Content-Type')) {
      request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') });
    }
    return next.handle(request)
      .pipe(
        retry(1),
        catchError((error: HttpErrorResponse) => {
          let errorMessage = '';
          if (error.error instanceof ErrorEvent) {
            // client-side error
            errorMessage = `${error.error.message}`;

          } else {

            // console.log(error)
            switch (error.status) {
              case 401: {
                console.log(error.error.error.message)
                console.log(error)

                if (error.error.error.message.includes('jwt expired')) {
                  console.log(true)
                  this.handle401Error(request, next)

                }
                else {
                  console.log(false)
                  this.router.navigate(['login'])

                }
              }
              default:
                //window.alert(error.error.error.message)
                return throwError(error);
            }
            // server-side error
          //  errorMessage = `${error.status}\n ${error.message}`;
          }
          //\  window.alert(errorMessage);
        //  return throwError(errorMessage);
        })
      )
  }

  private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
    console.log('refresh token')
    const refreshToken = localStorage.getItem('refreshtoken')
    console.log(refreshToken)
    this.loginService.refresh_token(refreshToken)
      .pipe(untilDestroyed(this))
      .subscribe(data => {
        console.log(data)
        localStorage.setItem('token', data.accessToken)
        const jwt = localStorage.getItem('token')
        console.log('401', jwt)
        if(jwt) {
          request = request.clone({
            setHeaders: {
              Authorization: `Bearer ${jwt}`
            }
          });
        }
        
        if (!request.headers.has('Content-Type')) {
          request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') });
        }
        return next.handle(request);

      })
  }
}

1 个答案:

答案 0 :(得分:-1)

您可以像这样使用s.th:

getposts() {
return this.http.post<any>(`${config.apiUrl}/post`, {
  'type': 1
}).pipe(
  tap(() => this.doLogoutUser()),
  mapTo(true),
  catchError(error => {
    if(error.status===401){
    return this.http.post<any>(`${config.apiUrl}/post`, {
  'type': 1
     });
    }
  }));
}

还添加了tis行以捕获拦截器的错误以引发错误:

return throwError(errorMessage);

因此您可以重试请求http.post的捕获错误,而无需重新加载页面