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.
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.
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. |
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 }
];
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.