gpt4 book ai didi

javascript - token 拦截器不会再次发送原始请求(Angular、Node.js)

转载 作者:行者123 更新时间:2023-11-30 19:06:27 26 4
gpt4 key购买 nike

我正尝试在我的 Angular 前端实现 token 拦截器,但我当前的实现存在一个问题。

我的拦截器是这样的:

  intercept(request: HttpRequest<any>,next: HttpHandler): Observable<HttpEvent<any>> {
if (request.headers.get("No-Auth") === "True") {
return next.handle(request);
}

return next.handle(request).pipe(
catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
this.handle404Error(request, next);
} else {
return throwError(error);
}
})
);
}

和 handle404Error 函数:

  handle404Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);

return this.authService.refreshToken().subscribe(
(res: any) => {
if (Boolean(res) === true) {
this.isRefreshing = false;
this.refreshTokenSubject.next(res);
return next.handle(request);
} else {
return this.authService.logout();
}
},
err => {
return this.authService.logout();
},
() => {
this.isRefreshing = false;
}
);
} else {
return this.refreshTokenSubject.pipe(
filter(res => res != null),
take(1),
switchMap(() => {
return next.handle(request);
})
);
}
}

当我进行 API 调用并且服务器返回 404 时,我的拦截器将调用 /token 端点以获取新的 JWT。

请注意,我将 JWT 存储在服务器(内存中)的 session 对象中,而在客户端,我只有 sessionID 和刷新 token 作为 HttpOnly cookie。

问题是,当我进行 API 调用并且 JWT 无效时,它会设置新的 JWT,但不会再次发送之前的请求。 (JWT 过期后,我必须按两次按钮才能获取数据)。

你知道如何实现这个逻辑吗?

谢谢你的帮助。

最佳答案

第一件事是不对的——你在拦截器中订阅,所以你得到了嵌套订阅,因为 Angular 在内部订阅了你的请求。

您真正想要的是从 catchError 返回您的 return next.handle(request);。示例:

return next.handle(request).pipe(
catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle404Error(request, next);
} else {
return throwError(error);
}
})
);

handle404Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);

return this.authService.refreshToken().pipe(
mergeMap((res: any) => {
if (Boolean(res) === true) {
this.isRefreshing = false;
this.refreshTokenSubject.next(res);
return next.handle(request);
} else {
/* return */ this.authService.logout();
return of(undefined) // added this because I dont know what this.authService.logout() returns. It must be an Observable
}
}),
catchError((err) => {
/* return */ this.authService.logout();
return throwError(err);
}))
} else {
return this.refreshTokenSubject.pipe(
filter(res => res != null),
take(1),
switchMap(() => {
return next.handle(request);
})
);
}
}

请注意,我没有检查任何拼写错误。我也丢弃了这个 block :

() => {
this.isRefreshing = false;
}

如果你想在 this.authService.refreshToken() 完成时执行它,你可以在 mergeMap 旁边添加 finalize 运算符并且catchError.

解释这里实际发生的事情很简单 - 你从 intercept 方法返回 one Observable。只需将所有 API 调用通过管道连接在一起,返回的流就会执行它们。

关于javascript - token 拦截器不会再次发送原始请求(Angular、Node.js),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58937972/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com