2016-02-12 9 views
8

ich einen Winkel 2-Anwendung habe, in dem ich muß auf jeder Seite authentifiziert werden. Also habe ich ein benutzerdefiniertes RouterOutlet implementiert, um zu bestätigen, dass ich bei jedem Seitenwechsel angemeldet bin.Angular 2-Authentifizierung mit Kind Routen

@Directive({ 
    selector: 'auth-outlet' 
}) 
export class AuthOutlet extends RouterOutlet { 
    publicRoutes: any; 
    private parentRouter: Router; 
    private authService: AuthService; 
    constructor(_elementRef: ElementRef, 
       _loader: DynamicComponentLoader, 
       _parentRouter: Router, 
       @Attribute('name') nameAttr: string, 
       _authService: AuthService) { 

     super(_elementRef, _loader, _parentRouter, nameAttr); 
     this.parentRouter = _parentRouter; 
     this.authService = _authService; 
     this.publicRoutes = { 
      'Login': true 
     }; 
    } 

    activate(oldInstruction: ComponentInstruction) { 
     var url = this.parentRouter.lastNavigationAttempt; 
     console.log('attemping to nav'); 
     if (!this.publicRoutes[url] && !this.authService.loggedIn){ 
      var newInstruction = new ComponentInstruction('Login', [], new RouteData(), Login, false, 1); 
      return super.activate(newInstruction); 
     } else { 
      return super.activate(oldInstruction); 
     } 
    } 
} 

Hier ist ein funktionierendes Code: http://plnkr.co/edit/YnQv7Mh9Lxc0l0dgAo7B?p=preview

Gibt es einen besseren Weg, Routenänderungen abzufangen und für die Anmeldung umleiten, wenn der Benutzer nicht authentifiziert ist?

+1

Superb !! Was brauchst du noch !! – micronyks

+0

Nun, für eine Sache sollten Sie nicht eine ComponentInstruction neu erstellen. Das hat also schon Probleme. Außerdem treten Probleme auf, wenn Sie sich in einer untergeordneten Route befinden, die nicht über die Anmeldungsroute informiert ist. (Ich arbeitete an diesem Problem mit dem Poster) –

+0

Wenn jemand tief mit der Seite verlinkt, wird der Server beteiligt und Sie machen eine Authentifizierung auf dem Server. Wenn jemand autorisiert ist, gelangen Sie in Ihre App. Sobald sie sich in Ihrer App befinden, können sie sich frei bewegen. Der Browser und js sollten hier keine Auth-Checks machen, der Server sollte. –

Antwort

8

Für alle, die diese findet, ist die Antwort jetzt in Angular 2 „Guards“ als Teil des neuen Router zu verwenden. Siehe Angular 2 Dokumentation:

https://angular.io/docs/ts/latest/guide/router.html#!#guards

Eine grundlegende Wache gerade implementiert „CanActivate“ und arbeiten konnte wie folgt:

import {Injectable} from "@angular/core"; 
import {CanActivate, Router} from "@angular/router"; 
import {AuthService} from "../services/auth.service"; 

@Injectable() 
export class AuthGuard implements CanActivate { 
    constructor(private authService:AuthService, private router:Router){} 

    canActivate(){ 
     if(this.authService.isAuthenticated()) 
      return true; 

     this.router.navigate(["/login"]); 
     return false; 
    } 
} 

Wie Sie in diesem Beispiel sehen kann ich ein AuthService haben woanders läuft (Implementierung ist nicht wichtig), die dem Wächter mitteilen kann, ob der Benutzer authentifiziert wurde. Wenn sie haben, kehren Sie zurück und die Navigation geschieht wie gewohnt. Wenn nicht, geben wir false zurück und leiten sie zum Anmeldebildschirm um.

+0

Hallo John, willkommen in SO und danke für deine Antwort. Es wird davon abgeraten, Code-Only-Antworten zu empfehlen, da sich der Link im Laufe der Zeit ändern und ungültig werden kann - daher ist es viel besser, eine vollständige Antwort anzugeben, die hier allein stehen kann, wobei der Link als Referenz dient. Würde es Ihnen etwas ausmachen, Ihre Antwort so zu bearbeiten? Danke noch einmal! –

+0

@JohnAckerman Der Nachteil dieses Ansatzes im Vergleich zu OPs ist, dass wir diesen Wächter für alle auth erforderlichen Pfade erwähnen müssen, damit Duplikation und Verwendung von OP-Code können wir auch die letzte versuchte Route speichern und dann verwenden, um den Benutzer einmal einzuloggen ist erfolgreich. – lbrahim

+0

@Ibrahim nicht wirklich. Wenn Sie eine ganze Sektion (Modul?) Einer Site haben, die hinter der Wache sein muss, dann sollten Sie Ihre Routen entsprechend strukturieren. Sie brauchen nur die Wache auf der übergeordneten Ebene. Wenn Sie eine/admin-Route mit Kindern definieren, benötigt nur die Admin-Route den Wächter und die Kinder erben ihn. –

0

Sie können auch CanActivate verwenden, jedoch direkt DI zur Zeit nicht unterstützt wird. Hier ist eine nette workaround tho.

Viel Glück.

2

Hier ist ein aktualisierter Beispiel für eine AuthGuard mit kantigen 2 RC6.

Routen mit dem Weg nach Hause geschützt durch AuthGuard

import { Routes, RouterModule } from '@angular/router'; 

import { LoginComponent } from './login/index'; 
import { HomeComponent } from './home/index'; 
import { AuthGuard } from './_guards/index'; 

const appRoutes: Routes = [ 
    { path: 'login', component: LoginComponent }, 

    // home route protected by auth guard 
    { path: '', component: HomeComponent, canActivate: [AuthGuard] }, 

    // otherwise redirect to home 
    { path: '**', redirectTo: '' } 
]; 

export const routing = RouterModule.forRoot(appRoutes); 

AuthGuard Umleitungen zur Login-Seite, wenn der Benutzer nicht angemeldet ist

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

@Injectable() 
export class AuthGuard implements CanActivate { 

    constructor(private router: Router) { } 

    canActivate() { 
     if (localStorage.getItem('currentUser')) { 
      // logged in so return true 
      return true; 
     } 

     // not logged in so redirect to login page 
     this.router.navigate(['/login']); 
     return false; 
    } 
} 

Für das gesamte Beispiel und Demo arbeiten Sie können Besuche this post

Verwandte Themen