Saltar al contenido

Intentando repetir una solicitud http después de actualizar el token con un interceptor en angular 7

Solución:

Tienes que distinguir entre todas las solicitudes. Por ejemplo, no desea interceptar su solicitud de inicio de sesión y tampoco la solicitud de token de actualización. SwitchMap es su mejor amigo porque necesita cancelar algunas llamadas para esperar a que su token se actualice.

Entonces, lo que debe hacer es verificar primero las respuestas de error con el estado 401 (no autorizado):

return next.handle(this.addToken(req, this.userService.getAccessToken()))
            .pipe(catchError(err => {
                if (err instanceof HttpErrorResponse) {
                    // token is expired refresh and try again
                    if (err.status === 401) {
                        return this.handleUnauthorized(req, next);
                    }

                    // default error handler
                    return this.handleError(err);

                } else {
                    return observableThrowError(err);
                }
            }));

En su función handleUnauthorized, debe actualizar su token y también omitir todas las solicitudes adicionales mientras tanto:

  handleUnauthorized (req: HttpRequest<any>, next: HttpHandler): Observable<any> {
        if (!this.isRefreshingToken) {
            this.isRefreshingToken = true;

            // Reset here so that the following requests wait until the token
            // comes back from the refreshToken call.
            this.tokenSubject.next(null);
            // get a new token via userService.refreshToken
            return this.userService.refreshToken()
                .pipe(switchMap((newToken: string) => {
                    // did we get a new token retry previous request
                    if (newToken) {
                        this.tokenSubject.next(newToken);
                        return next.handle(this.addToken(req, newToken));
                    }

                    // If we don't get a new token, we are in trouble so logout.
                    this.userService.doLogout();
                    return observableThrowError('');
                })
                    , catchError(error => {
                        // If there is an exception calling 'refreshToken', bad news so logout.
                        this.userService.doLogout();
                        return observableThrowError('');
                    })
                    , finalize(() => {
                        this.isRefreshingToken = false;
                    })
                );
        } else {
            return this.tokenSubject
                .pipe(
                    filter(token => token != null)
                    , take(1)
                    , switchMap(token => {
                        return next.handle(this.addToken(req, token));
                    })
                );
        }
    }

Tenemos un atributo en la clase de interceptor que verifica si ya hay una solicitud de token de actualización en ejecución: this.isRefreshingToken = true; porque no desea tener varias solicitudes de actualización cuando activa varias solicitudes no autorizadas.

Así que todo dentro del if (!this.isRefreshingToken) parte se trata de actualizar su token e intentar la solicitud anterior nuevamente.

Todo lo que se maneja en else es para todas las solicitudes, mientras tanto, mientras su userService actualiza el token, se devuelve un tokenSubject y cuando el token está listo con this.tokenSubject.next(newToken); Se reintentará cada solicitud omitida.

Aquí este artículo fue la inspiración de origen para el interceptor: https://www.intertech.com/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/

EDITAR:

TokenSubject es en realidad un sujeto de comportamiento: tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);, lo que significa que cualquier suscriptor nuevo obtendrá el valor actual en la transmisión, que sería el token anterior de la última vez que llamamos this.tokenSubject.next(newToken).

Connext(null) cada nuevo suscriptor no activa el switchMap parte, por eso filter(token => token != null) es necesario.

Después this.tokenSubject.next(newToken) se llama de nuevo con un nuevo token, cada suscriptor activa el switchMap parte con la ficha nueva. Espero que sea más claro ahora

EDITAR 21.09.2020

Corregir enlace

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *