2016-02-12 22 views
8

Ho un'applicazione angolare 2 in cui devo essere autenticato su ogni pagina. Quindi ho implementato un RouterOutlet personalizzato per confermare che ho effettuato l'accesso ad ogni cambio di pagina.Angolare 2 Autenticazione con percorsi figlio

@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); 
     } 
    } 
} 

Ecco un codice di lavoro: http://plnkr.co/edit/YnQv7Mh9Lxc0l0dgAo7B?p=preview

Esiste un modo migliore per intercettare i cambiamenti di rotta e reindirizzare per il login quando l'utente non è autenticato?

+1

Superlativo !! Cos'altro hai bisogno !! – micronyks

+0

Bene, per prima cosa non si dovrebbe creare una ComponentInstruction. Quindi questo ha già dei problemi. Inoltre presenta problemi se ti trovi in ​​una rotta secondaria che non conosce la rotta di accesso. (Ho lavorato su questo problema con il poster) –

+0

Se qualcuno collega i collegamenti alla pagina, il server viene coinvolto e tu fai un controllo di autenticazione sul server. Se qualcuno è autorizzato, entra nella tua app. Una volta nella tua app, possono muoversi liberamente. Il browser e js non dovrebbero fare controlli di autenticazione qui, il server dovrebbe. –

risposta

8

Per chi trova questo, la risposta ora in Angular 2 è di utilizzare "Guardie" come parte del nuovo router. Vedere angolare 2 documentazione:

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

Una guardia di base solo implementa "CanActivate", e potrebbe funzionare come segue:

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

Come si può vedere in questo esempio ho un AuthService correre da qualche altra parte (l'implementazione non è importante) che può dire alla guardia se l'utente è stato autenticato. Se hanno, restituiscono true e la navigazione avviene come al solito. In caso contrario, restituiamo false e li reindirizziamo alla schermata di accesso.

+0

Ciao John, benvenuto in SO e grazie per la tua risposta. Le risposte al solo codice sono sconsigliate perché il collegamento può cambiare nel tempo e diventare invalidato, quindi è molto meglio fornire una risposta completa che può stare qui da sola, con il link come riferimento. Ti dispiacerebbe modificare la tua risposta con questo in mente? Grazie ancora! –

+0

@JohnAckerman Ma lo svantaggio di questo approccio rispetto a quello di OP è che dobbiamo menzionare questa guardia per tutti i percorsi richiesti dall'autorizzazione in modo duplicazione e utilizzando il codice OP possiamo anche memorizzare l'ultimo tentativo di percorso e quindi utilizzare per reindirizzare l'utente una volta il login ha successo – lbrahim

+0

@Ibrahim non proprio. Se hai un'intera sezione (modulo?) Di un sito che deve essere dietro la guardia, allora dovresti strutturare i tuoi percorsi di conseguenza. Hai solo bisogno della guardia a livello dei genitori. Se si definisce una rotta/admin con i bambini, l'unica route admin ha bisogno della guardia e i bambini la ereditano. –

0

È inoltre possibile utilizzare CanActivate, tuttavia il DI diretto non è al momento supportato. Ecco un bel workaround tho.

Buona fortuna.

2

Ecco un esempio aggiornato di utilizzo di AuthGuard con Angular 2 RC6.

Itinerari con percorso casa protetti da 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 reindirizza alla pagina di login se l'utente non è connesso

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

Per l'esempio completo e demo è possibile lavorare check out this post

Problemi correlati