角度无缝刷新令牌流

时间:2018-03-22 13:08:18

标签: angular

我有一个系统,我将一个刷新令牌(长寿命)和一个访问令牌(短期)返回给Angular前端。

目前,仅设置访问令牌。 我有HttpInterceptor设置,我按照这样注入访问令牌:

 intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        let token = this.somewhere.getToken();

        let requestToHandle: HttpRequest<any> = req;
        if (token != null && token.length > 0) {
            const clonedRequest = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + token) });
            requestToHandle = clonedRequest;
        }

        return next.handle(requestToHandle).catch((err: HttpErrorResponse) => {
             // some error handling here
        });
}

现在我正在添加刷新令牌,我希望系统在我们获得401(内部.catch()块)时尝试为访问令牌交换刷新令牌。

但是,由于循环依赖,我无法向我的拦截器注入HttpClient。 (我也尝试使用Injector,没有运气)。

更新将Angular更新为5.2.9后,我实际上可以注入HttpClient

我添加了这样的代码:

return next.handle(requestToHandle).catch((err: HttpErrorResponse) => {

    if (!(err.error instanceof Error)) {
        if (err.status === 401) {
            this.http.post<Token>('http://somewhere' + '/somerfreshtokenapi',
                {
                    refresh_token: this.someService.refreshToken
                }).subscribe(result => {
                    let requestClone = requestToHandle.clone({ headers: req.headers.set('Authorization', 'Bearer ' + result.token) });
                    requestToHandle = requestClone;
                    // how do i wire this back to `next.handle()`?
                    return this.httpClient.request(requestToHandle);
                }, e => {
                    // some error handling here
                });
        });

    }

return Observable.throw(err);
});

2 个答案:

答案 0 :(得分:1)

只需使用switchMap而不是订阅,并使用新令牌执行失败的请求:

if (err.status === 401) {
  this.http.post<Token>(...)
    .switchMap(result => {
       let requestClone = requestToHandle.clone({ headers: req.headers.set('Authorization', 'Bearer ' + result.token) });
       return next.handle(requestClone)
     }, e => {
       // some error handling here
     });
}

答案 1 :(得分:-1)

只需进行递归通话?

return next.handle(requestToHandle).catch((err: HttpErrorResponse) => {
  if(err && err.status === 401) {
    const clone = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + refreshedToken) });
    return this.intercept(clone, next);
  }

  return Observable.throw(err);
});
相关问题