尝试在http拦截器中捕获401,刷新我的会话并重试原始请求

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尝试在http拦截器中捕获401,刷新我的会话并重试原始请求相关的知识,希望对你有一定的参考价值。

我试图拦截从/api返回的响应,捕获它们,如果它们401,执行刷新会话操作,然后再次重试原始HTTP调用(另外防止它无限循环,如果它再次401s)

我认为我在下面的代码中正在做的是使用http处理程序触发请求,订阅它的事件,如果它在401上失败,则刷新然后返回由处理程序执行的克隆请求的observable。

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (!request.url.startsWith('/api')) {
        return next.handle(request)
    }

    const cloned = request.clone()
    return next.handle(request)
        .pipe(
            catchError((error: any) => {
                if (error.status !== 401) {
                    return throwError(error)
                }
                return from(this.sessionService.refresh())
                    .pipe(map(() => next.handle(cloned)))
            })
        )
}

关于如何实现我的目标的任何建议?

答案

可能有一些语法错误,因为我正在从移动设备写作,但这应该让你开始

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!request.url.startsWith('/api')) {
    return next.handle(request)
}

const cloned = request.clone()
return next.handle(request)
    .do((event: HttpEvent<any>) =>
        return from(this.sessionService.refresh())
               .pipe(map(() => next.handle(cloned)))
        }), (err: any) => {
             if (err instanceof HttpResponse) {
                  if(err.status === 401){
                       return throwError(error);
                  }
        }
    )
}
另一答案

答案是使用switctMap而不是map

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
{
    if (!request.url.startsWith('/api')) {
        return next.handle(request)
    }

    const cloned = request.clone()
    return next.handle(request)
        .pipe(
            catchError((error: any) => {
                if (error.status !== 401) {
                    return throwError(error)
                }
                return from(this.sessionService.refresh())
                    .pipe(switchMap(() => next.handle(cloned)))
        })
    )
}

但是,我选择了另一种方法,在检查请求发生之前是否有会话,如果需要,请注入刷新操作。

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (
        !request.url.startsWith('/api') || 
        this.sessionService.isValid
    ) {
        return next.handle(request)
    }

    return from(this.sessionService.refresh())
        .pipe(switchMap(() => next.handle(request)))
}

以上是关于尝试在http拦截器中捕获401,刷新我的会话并重试原始请求的主要内容,如果未能解决你的问题,请参考以下文章

令牌刷新后Angular 4拦截器重试请求

Vue 资源拦截器刷新 JWT 令牌

在 JWT 刷新时出现 401 时重定向

多个请求的 axios 拦截器刷新令牌

AngularJS 中的 401 未经授权的错误处理

Android OkHttp,刷新过期令牌