Angular 5 Http Interceptor 刷新 JWT 令牌 [英] Angular 5 Http Interceptor refreshing JWT token

查看:23
本文介绍了Angular 5 Http Interceptor 刷新 JWT 令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现了令牌保存、检索的逻辑,我也有刷新调用.问题是,当我在 HttpInterceptor 中拦截 403 时,同时进行的其他调用也会刷新令牌.我很想保留这些电话,直到我的令牌刷新.创建我称之为请求的信号量".

I already have implemented logic of token saving, retrieving and I have refreshing call also. The problem is that when I intercept 403 in my HttpInterceptor, other calls that are made at the same time, also refresh the token. I would love to hold those calls until my token is refreshed. To create what I would call a 'semaphore' of requests.

@Injectable()
export class TokenInterceptor implements HttpInterceptor {

private auth: AuthService;

constructor(private injector: Injector) {
}

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.auth = this.injector.get(AuthService);

    if(this.auth.isAuthenticated()){
        request = request.clone({
            setHeaders: {
                Accept: 'application/json',
                Authorization: `Bearer ${localStorage.getItem('access_token')}`
            }
        });
    } else {
        request = request.clone({
            setHeaders: {
                Accept: 'application/json'
            }
        });
    }

    return next.handle(request).catch(error => {
        if (error.status === 401) {
            console.log('refreshing token');

            // TODO: return Refresh Token here and hold other calls
        }

        return Observable.throw(error);
    });
}

推荐答案

好吧,我无法设置环境来测试此逻辑是否正常工作,但我已尽力了:

Well, I'm not able to setup an enviroment to test if this logic works properly, but I tried my best:

你的拦截器应该是这样的:

Your interceptor should be something like:

@Injectable()
export class TokenInterceptor implements HttpInterceptor {

  private auth: AuthService;

  constructor(private injector: Injector) {
    this.auth = this.injector.get(AuthService);
  }

  setHeaders(request) {
    return function (token) {
      return request.clone({
        setHeaders: {
          Accept: 'application/json',
          Authorization: `Bearer ${token}`
        }
      });
    }
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return this.auth
      .getToken()
      .map(this.setHeaders(request))
      .mergeMap(next.handle)
      .catch(error => {
        if (error.status === 401) {
          return this.auth.refreshToken()
            .map(this.setHeaders(request))
            .mergeMap(next.handle);
        }
        return Observable.throw(error);
      });
  }

}

还有你的 AuthService:

And your AuthService:

@Injectable()
export class AuthService {

  private refreshTokenCall;

  saveTokenInLocalStorage(token) {
    localStorage.setItem('access_token', token);
  }

  getToken() {
    if (localStorage.getItem('access_token')) {
      return Observable.of(localStorage.getItem('access_token'));
    }

    return this.refreshToken();
  }

  refreshToken() {
    if (!this.refreshTokenCall) {
      this.refreshTokenCall = this.http.get(refreshTokenURL)
        // Maybe a .map() here, it depends how the backend returns the token
        .do(this.saveTokenInLocalStorage)
        .finally(() => this.refreshTokenCall = null);
    }
    return this.refreshTokenCall;
  }

}

希望能帮到你.

这篇关于Angular 5 Http Interceptor 刷新 JWT 令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆