刷新令牌拦截器的Angular 6问题

时间:2018-12-11 10:55:31

标签: angular jwt angular6

我的令牌拦截器有问题,我似乎找不到它,我必须说我是新手。 我正在关注this article,以了解如何刷新jwt令牌。

这是我的令牌拦截器服务:

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

@Injectable({
  providedIn: 'root'
})
export class TokenInterceptorService implements HttpInterceptor {

  constructor(private injector: Injector, private router: Router) {
  }
  inflightAuthRequest = null;

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.url.includes('login_check')) {
      return next.handle(req);
    }

    const authService = this.injector.get(AuthService);
    if (!this.inflightAuthRequest) {
      this.inflightAuthRequest = authService.getToken();
    }

    return this.inflightAuthRequest.pipe(
      map((token: string) => {
      // unset request inflight
      console.log('old token', this.inflightAuthRequest);
      this.inflightAuthRequest = null;
      console.log('unset inflighttoken');
      // use the newly returned token
      const authReq = req.clone({
      headers: req.headers.set('token', token ? token : '')
    });

    return next.handle(authReq);
  }),
      catchError(error => {
        console.log('we have an error');
        // checks if a url is to an admin api or not
        if (error.status === 401) {
          // check if the response is from the token refresh end point
          const isFromRefreshTokenEndpoint = !!error.body['message'];
          if (isFromRefreshTokenEndpoint) {
            localStorage.clear();
            this.router.navigate(['/login']);
            return throwError(error);
          }

          if (!this.inflightAuthRequest) {
            this.inflightAuthRequest = authService.refreshToken();                
            if (!this.inflightAuthRequest) {
              // remove existing tokens
              localStorage.clear();
              this.router.navigate(['/sign-page']);
              return throwError(error);
            }
          }
          return this.inflightAuthRequest.pipe(
            switchMap((token: string) => {
              // unset inflight request
              this.inflightAuthRequest = null;
              // clone the original request
              const authReqRepeat = req.clone({
                headers: req.headers.set('token', token)
              });
              // resend the request
              return next.handle(authReqRepeat);
            })
          );
        } else {
          return throwError(error);
        }
      })
    );
  }
}

拦截方法检查错误401(令牌过期时),然后检索另一个令牌。如果在令牌尚未刷新时用户发送了另一个请求,则该请求将首先等待响应。 拦截器使用getToken()和refreshToken()服务:

getToken(): Observable<string> {
    const decoder = new JwtHelperService();
    const token = localStorage.getItem('token');
    const isTokenExpired = decoder.isTokenExpired(token);

    if (!isTokenExpired) {
      return of(token);
    }

    return this.refreshToken();
  }

  refreshToken(): Observable<string> {
    const url = environment.apiUrl + 'api/token/refresh';

    // append refresh token if you have one
    const refreshToken = localStorage.getItem('refreshToken');
    const expiredToken = localStorage.getItem('token');

    const httprequest = this.http
      .get(url, {
        params: new HttpParams()
          .set('refresh_token', refreshToken),
        observe: 'response'
      })
      .pipe(
        share(),
        map(res => {
          const token = res.headers.get('token');
          const newRefreshToken = res.headers.get('refresh_token');

          // store the new tokens
          localStorage.setItem('refreshToken', newRefreshToken);
          localStorage.setItem('token', token);

          return token;
        })
      );
    return httprequest;
  }

我发现浏览器没有向后端发送任何请求,所以我认为问题出在请求上。

0 个答案:

没有答案