webentwicklung-frage-antwort-db.com.de

Angular 4.3 Abfangjäger - Wie benutzt man?

Ich bin dabei, eine neue App zu erstellen, für die Autorisierungs-Header erforderlich sind. Normalerweise benutze ich etwas sehr Ähnliches wie in diesem scotch.io Artikel . Es ist mir jedoch aufgefallen, dass HTTP-Interceptors jetzt im Angular 4-Ökosystem über das neue HttpClientModule vollständig unterstützt werden, und ich versuche, eine Dokumentation zu finden, wie man sie genau verwendet.

Wenn ich mich in (ab 4.3) geirrt habe und dies die beste Vorgehensweise zum Einfügen von Autorisierungs-Headern ist, bin ich auch offen für Vorschläge. Ich war der Meinung, dass dieses Feature kürzlich hinzugefügt wurde, was bedeutet, dass es wahrscheinlich einen guten Grund gibt, auf eine "Angular Approved" -Methode umzusteigen.

6
joshrathke

Diese Antwort entlehnt die offizielle Dokumentation von CodeWarrior.

In Angular können Sie einen HttpInterceptor erstellen:

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

@Injectable()
export class NoopInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req);
  }
}

die Sie dann wie folgt in Ihre App integrieren können:

import {NgModule} from '@angular/core';
import {HTTP_INTERCEPTORS} from '@angular/common/http';

@NgModule({
  providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: NoopInterceptor,
    multi: true,
  }],
})
export class AppModule {}

Um einen Berechtigungsheader hinzuzufügen, können Sie die Anforderung mit den geänderten Kopfzeilen klonen:

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

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private auth: AuthService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Get the auth header from the service.
    const authHeader = this.auth.getAuthorizationHeader();
    // Clone the request to add the new header.
    const authReq = req.clone({headers: req.headers.set('Authorization', authHeader)});
    // Pass on the cloned request instead of the original request.
    return next.handle(authReq);
  }
}

Beachten Sie, dass die Interzeptoren sich wie eine Kette verhalten. Sie können also mehrere Interzeptoren einrichten, um verschiedene Aufgaben auszuführen.

9
John

Beim Einspritzen von AuthService in den Konstruktor des Interceptors gab es diesen Fehler: 

Nicht erfasster Fehler: Fehler beim Provider-Parsing: Die zyklische Abhängigkeit Kann nicht instanziiert werden! InjectionToken_HTTP_INTERCEPTORS ("[ERROR ->]"): in NgModule AppModule in ./[email protected]:-1

Anstatt es dem Konstruktor zu injizieren, habe ich Injector von @angular/core verwendet und es hat gut funktioniert. Ich speichere das Token in localStorage und verwende grundlegende Auth. Ich muss einstellen 

Authorization: 'Bearer token_string'

So habe ich implementiert:  

token.interceptor.ts

import {Injectable, Injector} from '@angular/core';

import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {AuthService} from './auth.service';

@Injectable()
export class TokenInterceptor implements HttpInterceptor {

    constructor(private injector: Injector) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        const auth = this.injector.get(AuthService);
        if (auth.getToken()) {
            request = request.clone({
                setHeaders: {
                    Authorization: `Bearer ${auth.getToken()}`
                }
            });

        }

        return next.handle(request);
    }
}

getToken-Funktion in AuthService

Hier können Sie die gesamte Logik implementieren, um den Header oder nur das Token abzurufen. In meinem Fall rufe ich dies nur an, um den JWT-Token-String zu erhalten. 

/**
 * Get jwt token
 * @returns {string}
 */
getToken(): string {
    return localStorage.getItem('token');
}

app.module.ts

Importieren Sie die TokenInterceptor

import {TokenInterceptor} from './pathToTheFile/token.interceptor';

fügen Sie unter @NgModule im providers:-Array Folgendes hinzu.

providers: [
    {
        provide: HTTP_INTERCEPTORS,
        useClass: TokenInterceptor,
        multi: true
    }
    //, other providers
]
3
Lahar Shah

Das Problem, das ich mit dem empfohlenen Ansatz hatte, war, dass die Interceptors zur Kompilierzeit bekannt sein mussten und anscheinend alle im selben Modul waren. 

Ich entschied mich für die Implementierung eines Interceptors und einer Kette von Handlerfunktionen, die zur Laufzeit erweitert werden können. Die Abfangmethode des Dienstes kümmert sich um die next () - Logik.

Der Service (Basiscode, keine Validierungen oder Wartung):

export type HttpHandlerFunction = (req: HttpRequest<any>) => HttpRequest<any>;

@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
    private _handlers: Array<HttpHandlerFunction> = [];

    addHandler(handler: HttpHandlerFunction): void {
        this._handlers.Push(handler);
    }

    intercept(req: HttpRequest<any>, next: HttpHandler):
        Observable<HttpEvent<any>> {
            this._handlers.forEach((handler: HttpHandlerFunction) => {
                req = handler(req);
            })
        return next.handle(req);
    }
}

Und die Verwendung in einem Dienst in einem anderen Modul:

constructor(injector: Injector) {

    const interceptorsArray: Array<any> = injector.get(HTTP_INTERCEPTORS),
        interceptor: HttpInterceptorService = interceptorsArray &&
            interceptorsArray.filter((i: any) => i instanceof HttpInterceptorService)[0];
    if (interceptor) {
        interceptor.addHandler((req: HttpRequest<any>) => {
            const accessToken = this.getAccessToken();
            if (accessToken) {
                // doesn't work with direct headers.set, you must clone
                req = req.clone({ headers: req.headers.set('Authorization', accessToken) });
            }
        return req;
    });
}
0
dfl