Angular 2 – So schützen Sie Routes mit Guards

Angular 2 hat mit «Guards» ein Feature eingeführt, mit dem man vor dem Auflösen einer Route bestimmte Kriterien prüfen kann.

Autor/in Fabian Gosebrink
Datum 17.11.2016
Lesezeit 6 Minuten

Angular 2 hat mit «Guards» ein Feature eingeführt, mit dem man vor dem Auflösen einer Route bestimmte Kriterien prüfen kann.

Dieses Angular 2 Feature ist gerade bei sicherheitsrelevanten Daten oder Views sinnvoll, da man aufgrund eines Tokens oder eines bestimmten Claims im Token prüfen kann, ob der derzeitige Benutzer mit dem Token x auf eine bestimmte Route zugreifen darf.


AngularJS by Google

Was ist Angular 2?

Angular 2 ist die zweite komplett überarbeitete Version des OpenSource Frameworks AngularJS von Google. Das Webframework kommt beim Erstellen von Single-Page-Applikationen zum Einsatz.

>> Website von AngularJS by Google


Angular 2 bietet zum Schützen von Routen vier Guards an: CanLoad, CanActivate, CanActivateChild, CanDeactivate.

Anmerkung: Ein Angular 2 Guard kann ein observable <boolean>, ein promise <boolean> oder ein boolean zurückgeben. Bei den asynchronen Operatoren wird gewartet, bis das Ergebnis true oder false ist. In den Beispielen in diesem Beitrag schauen wir uns nur die boolschen Operatoren true/false an.

Angular 2 Guard CanActivate

CanActivate prüft in Angular 2 vor dem Laden der Route, ob diese aufgelöst werden kann. Der Guard selber lässt sich am besten in einer Klasse implementieren. Er implementiert das CanActivate-Interface, und die gleichnamige Methode muss die Parameter «ActivatedRouteSnapshot» und «RouterStateSnapshot» als Parameter empfangen.

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

@Injectable()
export class AuthenticationGuard implements CanActivate {
   constructor(private router: Router) { }
   canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
       let url: string = state.url;
       return this.userIsLoggedIn(url);
   }
   private userIsLoggedIn(url: string): boolean {
       return true;
   }
}

Die Klasse muss dazu mit dem Injectable-Attribut markiert und als Provider im dazugehörigen Modul angeboten werden.

@NgModule({
   imports:
       // ...
   ,
   declarations:
       // ...
   ,
   providers:
       AuthenticationGuard
   ,
   // ...
})

Anschliessend kann im Router-Modul der CanActivate-Guard für die entsprechende Route aktiviert werden.

import { Routes } from '@angular/router';
import { HomeComponent } from './components/home/home.component';
import { AboutComponent } from './components/about/about.component';
import { AuthenticationGuard } from './guards/authentication';

export const AppRoutes: Routes =
   { path: '', redirectTo: '/home', pathMatch: 'full' },
   { path: 'home', component: HomeComponent },
   { path: 'about', component: AboutComponent, canActivate: [AuthenticationGuard }
];

angular-2-guards-fabian-gosebrink-digicomp
Auf dem Screenshot sieht man, dass die Route noch nicht aufgelöst wurde, der Guard aber durchlaufen wird. Eine Möglichkeit des Guards wäre nun das Umleiten auf eine andere Route, wenn der User nicht eingeloggt ist oder nicht über entsprechende Rechte verfügt.

Guards werden in Angular 2 in einem Array angegeben. Daher kann man Guards auch aneinanderreihen.

{ path: 'about', component: AboutComponent, canActivate: AuthenticationGuard, XyzGuard, ... }

Angular 2 Guard CanActivateChild

Der Angular 2 Guard «CanActivateChild» ist im Prinzip genau das gleiche wie der «CanActivate», es wird jedoch auf Child-Ebene im Routing-Modul angegeben.

Angular 2 Guard CanDeactivate

Der Guard «CanDeactivate» ist das Gegenteil von CanActivate: Er prüft also, ob eine Route verlassen werden darf. Beispielsweise, falls ungespeicherte Änderungen auf der Seite sind oder man aus anderen Gründen das Verlassen einer Seite bestätigen lassen will.

import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { AboutComponent } from '../components/about/about.component';

@Injectable()
export class CanDeactivateGuard implements CanDeactivate {
   canDeactivate(component: AboutComponent) {
       // parameter “component” represents your component here
       return component.MyCanDeactivate ? component.MyCanDeactivate() : true;
 }
}

Hierbei sieht man, dass der CanDeactivate-Guard generisch ist und den konkreten Komponententypen kennt. Einen Verweis auf die Instanz bekommt man als Parameter im Konstruktor übergeben. Man kann dann auf ihm durch einen Methodenaufruf beispielsweise abfragen, ob die Route verlassen werden darf oder nicht.

Wieder kann der Angular 2 Guard in der Route mit der entsprechenden Property angegeben werden.

import { Routes } from '@angular/router';
import { HomeComponent } from './components/home/home.component';
import { AboutComponent } from './components/about/about.component';
import { AuthenticationGuard } from './guards/authenticationGuard';
import { CanDeactivateGuard } from './guards/canDeactivateGuard';

export const AppRoutes: Routes =
   { path: '', redirectTo: '/home', pathMatch: 'full' },
   { path: 'home', component: HomeComponent },
   { path: 'about', component: AboutComponent,
       canActivate: [AuthenticationGuard,
       canDeactivate: CanDeactivateGuard
 }
];

Angular 2 Guard CanLoad

Der CanLoad-Guard kann benutzt werden, wenn man Routen erst gar nicht laden will bzw. wenn sie gar nicht geladen werden können. Die Routen sollen erst geladen werden, wenn ein bestimmtes Kriterium erfüllt ist.

Die Implementierung ist ähnlich wie die vorherigen Guards. Wieder wird das «CanLoad» importiert und implementiert.

import { Injectable } from '@angular/core';
import { CanLoad, Route } from '@angular/router';

@Injectable()
export class CanLoadGuard implements CanLoad {
   constructor() { }
   canLoad(route: Route): boolean {
       // return if criteial is fulfilled
       console.log("In Canload");
       return true;
   }
}

Der CanLoad-Guard funktioniert nur mit Lazy-Loading. Die Route wird durch Lazy-Loading nachgeladen, sobald die CanLoad-Methode nach Überprüfung eines Kriteriums true zurückgibt.

Fazit zu Route Guards in Angular 2

Somit sind Guards in Angular 2 ein sehr mächtiges Werkzeug, wenn man das Laden von Routen einschränken oder verhindern will. Durch die Verwendung von eigenen Typescript-Klassen und der Angabe in den Routen des Moduls bleiben die Kriterien übersichtlich und gut testbar – einer der vielen Vorteile von Angular 2.


Autor/in

Fabian Gosebrink

Fabian Gosebrink ist Microsoft MVP und leidenschaftlicher Webentwickler mit ASP.NET und bekannten Frameworks wie AngularJs. Als Professional Software Engineer berät und unterstützt er Kunden in der Schweiz bei der Umsetzung von Webapplikationen auch bis in den mobilen Bereich. Zudem ist er mehrmaliger Microsoft-Referent, Scrum-Enthusiast und aktiver Administrator der grössten deutschsprachigen C#-Community.