Hola, hemos encontrado la solución a lo que buscas, deslízate y la encontrarás más abajo.
Solución:
Para la solicitud de XHR, debe usar un Interceptor
Este es el que utilizo para agregar JWT a los encabezados y para manejar algunos errores de respuesta:
import Injectable from '@angular/core';
import
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor, HttpErrorResponse
from '@angular/common/http';
import AuthService from '../service/auth.service';
import Observable, of from 'rxjs';
import Router from "@angular/router";
import catchError from "rxjs/internal/operators";
@Injectable()
export class TokenInterceptor implements HttpInterceptor
constructor(public auth: AuthService, private router: Router)
/**
* intercept all XHR request
* @param request
* @param next
* @returns Observable
*/
intercept(request: HttpRequest, next: HttpHandler): Observable>
if (localStorage.getItem('jwtToken'))
request = request.clone(
setHeaders:
Authorization: 'Bearer ' + localStorage.getItem('jwtToken')
);
/**
* continues request execution
*/
return next.handle(request).pipe(catchError((error, caught) =>
//intercept the respons error and displace it to the console
console.log(error);
this.handleAuthError(error);
return of(error);
) as any);
/**
* manage errors
* @param err
* @returns any
*/
private handleAuthError(err: HttpErrorResponse): Observable
//handle your auth error or rethrow
if (err.status === 401)
//navigate /delete cookies or whatever
console.log('handled error ' + err.status);
this.router.navigate([`/login`]);
// if you've caught / handled the error, you don't want to rethrow it unless you also want downstream consumers to have to handle it as well.
return of(err.message);
throw err;
No olvide registrar su interceptor en app.module.ts
al igual que:
import TokenInterceptor from './auth/token.interceptor';
@NgModule(
declarations: [],
imports: [],
exports: [],
providers: [
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true,
],
bootstrap: [AppComponent]
)
export class AppModule
De la respuesta de @ firegloves, para tener el .pipe
los manipuladores de servicios individuales realmente pueden catchError
sus propios códigos de falla HTTP, deberá estructurar el código de tal manera que:
- Si el Interceptor detecta un código de error HTTP 401, manipúlelo y devuélvalo
of(error)
que potencialmente se puede manejar normalmente en cualquier subsiguiente.pipe
‘s. - Si el código de error HTTP es uno para el que Interceptor no está diseñado,
throw
nuevamente para que los controladores de errores posteriores, como los de sus servicios, puedan detectar y manejar errores que no sean 401 para sus propias llamadas.
Mi interceptor tiene un doble trabajo. Eso:
- Inyecta un
Authorization
encabezado en todas las solicitudes salientes, si tiene un token almacenado. - Intercepta errores HTTP 401 no autenticados, momento en el que invalida el almacén de tokens y luego vuelve a redireccionar a
/login
.
import Injectable from '@angular/core';
import Router from '@angular/router';
import
HttpErrorResponse,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
from '@angular/common/http';
import Observable from 'rxjs';
import catchError from 'rxjs/operators';
import of from 'rxjs/observable/of';
import AuthService from './auth.service';
@Injectable(
providedIn: 'root',
)
export class RequestInterceptor implements HttpInterceptor
constructor(
private readonly auth: AuthService,
private readonly router: Router,
)
/**
* @param HttpRequest request - The intercepted request
* @param HttpHandler next - The next interceptor in the pipeline
* @return Observable>
*/
intercept(request: HttpRequest, next: HttpHandler): Observable>
request = this.addToken(request);
return next.handle(request)
// add error handling
.pipe(
catchError(
(error: any, caught: Observable>) =>
if (error.status === 401)
this.handleAuthError();
// if you've caught / handled the error, you don't
// want to rethrow it unless you also want
// downstream consumers to have to handle it as
// well.
return of(error);
throw error;
),
);
/**
* Handle API authentication errors.
*/
private handleAuthError()
// clear stored credentials; they're invalid
this.auth.credentials = null;
// navigate back to the login page
this.router.navigate(['/login']);
/**
* Add stored auth token to request headers.
* @param HttpRequest request - the intercepted request
* @return HttpRequest - the modified request
*/
private addToken(request: HttpRequest): HttpRequest
const token: string = this.auth.token;
if (token)
return request.clone(
setHeaders:
Authorization: `Bearer $token`,
,
);
return request;
Todos AuthService
lo que hace es tener un get / set público que inserta un objeto de credenciales en localStorage
– se asegura de que el token no esté caducado, pero puedes diseñarlo como quieras.
Como @firegloves se indicó anteriormente, debe agregar el Interceptor a la tubería en app.module.ts
:
import RequestInterceptor from './auth/request.interceptor';
@NgModule(
declarations: [],
imports: [],
exports: [],
providers: [
provide: HTTP_INTERCEPTORS,
useClass: RequestInterceptor,
multi: true,
,
],
bootstrap: [AppComponent],
)
export class AppModule
valoraciones y reseñas
Si tienes alguna desconfianza y disposición de reformar nuestro división puedes dejar un comentario y con gusto lo interpretaremos.