代码之家  ›  专栏  ›  技术社区  ›  Yassine Younes

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

  •  0
  • Yassine Younes  · 技术社区  · 6 年前

    我的代币截取器有问题,我似乎找不到它,我必须说我是新的角度。 我在跟踪 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);
            }
          })
        );
      }
    }
    

    intercept方法检查错误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 回复  |  直到 6 年前