JWT 令牌刷新后返回重新调用
Posted
技术标签:
【中文标题】JWT 令牌刷新后返回重新调用【英文标题】:Return remaked call after JWT token refresh 【发布时间】:2019-10-10 17:48:14 【问题描述】:我正在使用 JWT,我有这样的逻辑:
-
进行http调用
如果令牌过期或结果返回401
返回 401 时,我必须进行 http 调用以要求新令牌
使用新令牌重新进行初始调用
返回结果
这个过程必须对用户隐藏。我已经捕获了 401 状态码并在检索新令牌后重复了原始调用,问题是将结果返回给原始调用。 这是带有 http 请求的服务:
getListCategories()
return this.http.get<Category[]>("/api/configuration/category").pipe(
catchError(err => this.handleError.handleError(err, severity: 'error', summary: 'Error retrieving the list of categories', life: 5000 ))
);
这是进行刷新调用并重复原始调用的错误拦截器:
export class ErrorInterceptorService implements HttpInterceptor
constructor(private auth: AuthService, public router: Router)
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
const shouldRetry = this;
return next.handle(request).pipe(
retryWhen(genericRetryStrategy(
shouldRetry
)),
catchError(err =>
//401 the token is invalid so I have to refresh it
if (err.status === 401 && request.url !== "/api/login")
this.auth.refreshToken().subscribe(
(apiResult: SessionTokenResponse) =>
this.auth.saveToken(apiResult.token);
request = request.clone( headers: request.headers.set('Authorization', 'Bearer ' + apiResult.token) );
next.handle(request).subscribe();
,
);
else if (err.status === 401 && request.url === "/api/login")
this.auth.logout()
else
const error = err.error.message || err.statusText;
return throwError(error);
),
)
private shouldRetry = (error) => (error.error instanceof ErrorEvent);
问题出在服务中,它不等待重拍调用,而是在第一个错误后退出。你能帮帮我吗?谢谢
【问题讨论】:
为什么要等待?你的refreshToken()
是异步的
对,但怎么能强迫它等待呢?
【参考方案1】:
您想返回 Observable
并执行链式操作,其中包括原始请求和重复请求之间的额外请求。我会尝试使用switchMap
来做到这一点。
应该是这样的:
catchError(err =>
if (err.status === 401 && request.url !== "/api/login")
//by returning observable here, you are "chaining" the calls so original caller will get this observable's result. `catchError` can be threated like `catch` block in `try-catch` where you can still do operations and return results - ergo continue operations.
return this.auth.refreshToken()
.switchMap( // this just switches from one observable to another
(apiResult: SessionTokenResponse) =>
this.auth.saveToken(apiResult.token);
request = request.clone( headers: request.headers.set('Authorization', 'Bearer ' + apiResult.token) );
return next.handle(request); // return original request handler with updated headers
,
);
显然没有经过测试,可能是此处所写的语法无效。
【讨论】:
我将 switchMap 放在管道中,它似乎可以工作,我正在测试它。谢谢以上是关于JWT 令牌刷新后返回重新调用的主要内容,如果未能解决你的问题,请参考以下文章