web-dev-qa-db-fra.com

Comment puis-je rediriger vers la page de connexion sur la réponse 401 dans Angular 5?

Je travaille sur une Angular 5 application utilisant le flux implicite OAuth2.

J'ai des services qui effectuent des appels HTTP, en suivant un exemple de mes services:

@Injectable()
export class MyService {

  constructor(public http: HttpClient) { }

  public getAll(): Observable<Persona[]> {
    return this.http.get<Persona[]>("http://mywebservice/persone");
  }
}

J'utilise des intercepteurs pour l'autorisation et j'ajoute des attributs personnalisés. Après mon intercepteur d'authentification:

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from "rxjs";

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor() {

  }
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    let accessToken = sessionStorage.getItem("access_token");
    if(accessToken)
    {
        request = request.clone({
        setHeaders: {
            Authorization: `Bearer ${accessToken}`
        }
        });
    }

    return next.handle(request);
  }
}

Et suivant la façon dont je consomme mes services:

public myMethod() {
    this.myService.getAll().subscribe(
        result => {
            console.log(result);
        }, error => {
            // I don't want add redirection there...
            console.error(error);
        });
}

Maintenant, mon besoin est que lorsque tout appel HTTP reçoit un résultat 401, l'application redirige l'utilisateur vers la page de connexion.

Comment puis-je obtenir ce résultat sans duplication de code?

Merci beaucoup

6
ilMattion

J'ai résolu mon problème en changeant mon intercepteur comme suit:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor() {

  }
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    let accessToken = sessionStorage.getItem("access_token");
    if(accessToken)
    {
        request = request.clone({
        setHeaders: {
            Authorization: `Bearer ${accessToken}`
        }
        });
    }

    return next.handle(request).do((event: HttpEvent<any>) => {
      if (event instanceof HttpResponse) {
      }
    }, (err: any) => {
      if (err instanceof HttpErrorResponse) {
        if (err.status === 401) {
            this.router.navigate(['login']);
        }
      }
    });
  }
}

J'ai trouvé la solution là-bas: https://medium.com/@ryanchenkie_40935/angular-authentication-using-the-http-client-and-http-interceptors-2f9d1540eb8

11
ilMattion

Seulement pour prendre en charge de nouveaux lecteurs, notez que dans angular 7, vous devez utiliser pipe () au lieu de do () ou catch ():

return next.handle(request).pipe(catchError(err => {
    if (err.status === 401) {
        MyComponent.logout();
    }
    const error = err.error.message || err.statusText;
        return throwError(error);
}));
10

Attachez la gestion des erreurs au gestionnaire de requêtes commun:

return next.handle(request).catch(err => {
    if (err.status === 401) {
         // Redirect here
    }
}

Vous pouvez importer le routeur directement dans l'intercepteur, mais la bonne façon de le faire est de créer un service d'authentification ou similaire qui importe le routeur et de l'appeler pour effectuer la redirection

1
Siro