【问题标题】:Angular interceptor - how do I logout if refresh token interceptor fails?Angular 拦截器 - 如果刷新令牌拦截器失败,我该如何注销?
【发布时间】:2020-06-03 08:31:15
【问题描述】:

信息

如果我收到 401,我正在创建一个拦截器来使用我的刷新令牌来更新我的访问令牌。现在的工作流程如下所示:

发送请求 > 获取 401 > 发送刷新请求 > 更新访问令牌 > 发送新请求

我目前正在使用 Promise 而不是 observables。


问题

如果最后一次请求失败,我该如何注销?

发送请求 > 获取 401 > 发送刷新请求 > 更新访问令牌 > 发送新请求 > 失败 > 注销

我有一个简单的注销方法,但我找不到在拦截器中放置它的位置。


代码

export class RefreshInterceptor implements HttpInterceptor {
    currentUser: User | null = null;
    private isRefreshing = false;
    private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(
        null
    );

    constructor(private authenticationService: AuthenticationService) {
        this.authenticationService.currentUser.subscribe(
            user => (this.currentUser = user)
        );
    }

    intercept(
        request: HttpRequest<any>,
        next: HttpHandler
    ): Observable<HttpEvent<any>> {
        return next.handle(request).pipe(
            catchError(error => {
                // check if user is signed in
                if (!this.currentUser) {
                    return throwError(error);
                }

                // handle only 401 error
                if (error instanceof HttpErrorResponse && error.status === 401) {
                    return from(this.handle401Error(request, next));
                } else {
                    return throwError(error);
                }
            })
        );
    }

    /**
     * Adds the new access token as a bearer header to the request
     * @param request - the request
     * @param token - the new access token
     */
    private async addToken(request: HttpRequest<any>, token: string) {
        const currentUser = this.authenticationService.currentUserValue;

        if (currentUser && currentUser.accessToken) {
            return request.clone({
                setHeaders: {
                    Authorization: `Bearer ${token}`
                }
            });
        }

        return request;
    }

    private async handle401Error(request: HttpRequest<any>, next: HttpHandler) {
        // check if it is currently refreshing or not
        if (!this.isRefreshing) {
            this.isRefreshing = true;
            this.refreshTokenSubject.next(null);

            // send refresh request
            const token = await this.authenticationService.getRefresh();

            // update bearer token
            const newRequest = await this.addToken(request, token);

            // update values for next request
            this.isRefreshing = false;
            this.refreshTokenSubject.next(token);
            return next.handle(newRequest).toPromise();
        } else {
            const token = this.refreshTokenSubject.value();
            const newRequest = await this.addToken(request, token);
            return next.handle(newRequest).toPromise();
        }
    }
}

【问题讨论】:

    标签: javascript angular jwt interceptor


    【解决方案1】:

    我用以下方法解决了:

    1. 修改了传出请求的标头,已更改(添加了重试标头,以便我稍后识别它)。
    2. 为注销创建了一个新的拦截器
    3. 查找带有重试标头的请求。签署了该请求。

    刷新令牌拦截器

    if (currentUser && currentUser.accessToken) {
                return request.clone({
                    setHeaders: {
                        Authorization: `Bearer ${token}`,
                        Retry: "true"
                    }
                });
            }
    

    注销拦截器

    @Injectable()
    export class LogoutInterceptor implements HttpInterceptor {
        constructor(private authenticationService: AuthenticationService) {}
    
        intercept(
            request: HttpRequest<any>,
            next: HttpHandler
        ): Observable<HttpEvent<any>> {
            return next.handle(request).pipe(
                catchError(error => {
                    // handle only 401 error
                    if (error instanceof HttpErrorResponse && error.status === 401) {
                        from(this.handleRequest(request));
                        return throwError(error);
                    }
    
                    return next.handle(request);
                })
            );
        }
    
        private async handleRequest(request: HttpRequest<any>) {
            const isRetriedRequest = request.headers.get("retry");
    
            if (isRetriedRequest) {
                await this.authenticationService.logout();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-31
      • 2017-12-26
      • 2018-06-12
      • 2023-03-23
      • 2020-05-12
      • 2019-07-09
      • 2019-03-28
      • 2019-09-03
      相关资源
      最近更新 更多