2016-06-18 10 views
8

ho letto la guida qui: https://angular.io/docs/ts/latest/guide/router.htmlAuthGuard non aspetta che l'autenticazione per terminare prima di controllare utente

sembra abbastanza semplice, tuttavia, non sono sicuro di come utilizzare l'autenticazione di angularfire2 all'interno di una guardia di autenticazione (canActivate). Quello che ho provato è:

AuthService

import { Injectable } from '@angular/core'; 
import { AngularFire } from 'angularfire2'; 

@Injectable() 
export class AuthService { 

    private user: any; 

    constructor(private af: AngularFire) { 
    this.af.auth.subscribe(user => { 
     this.user = user; 
    }) 
    } 

    get authenticated(): boolean { 
    return this.user ? true : false; 
    } 

} 

AuthGuard

@Injectable() 
export class AuthGuard implements CanActivate { 

    constructor(private router: Router, private authService: AuthService) { } 

    canActivate(): Observable<boolean> | boolean { 
    if (this.authService.authenticated) 
     return true; 

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

} 

Ho anche aggiunto AuthService per il bootstrap fornitori.

Questo tipo di funziona bene, tuttavia, il mio problema principale è quando aggiorno (o inizialmente carico) la pagina su che ha AuthGuard mi reindirizza sempre alla pagina di accesso poiché lo AuthGuard non attende la risposta di autenticazione. C'è un modo per attendere che l'autenticazione finisca (anche se è fallita) e quindi verificare se l'utente è autenticato?

+0

Vai a questa risposta, ha implementato guardia autenticazione correttamente http://stackoverflow.com/a/37889258/652850 –

+0

in realtà non risolvere il mio problema con angularfire2. – Andrew

risposta

11

Il problema è con il tuo codice. In AuthGuard controlli il risultato del metodo authenticated() che molto probabilmente restituirà falso poiché la proprietà dell'utente non è ancora impostata. Prova questo:

AuthService:

import { Injectable } from '@angular/core'; 
import { AngularFire } from 'angularfire2';'; 
import { Observable } from 'rxjs/Observable'; 

@Injectable() 
export class AuthService { 

    private user: any; 

    constructor(private af: AngularFire) { } 
    setUser(user) { this.user = user; } 
    getAuthenticated(): Observable<any> { return this.af.auth; } 
} 

AuthGuard:

@Injectable() 
export class AuthGuard implements CanActivate { 

    constructor(private router: Router, private authService: AuthService) { } 

    canActivate(): Observable<boolean> | boolean { 
    // here check if this is first time call. If not return 
    // simple boolean based on user object from authService 
    // otherwise: 

    return this.authService.getAuthenticated.map(user => { 
      this.authService.setUser(user); 
      return user ? true : false; 
    }) 

    } 
} 
+0

Grazie! C'è un modo per modificare questo in modo che ottenga i dati dell'utente nel costruttore AuthService? Con il modo in cui l'hai risolto, non ricevo i dati dell'utente solo su percorsi protetti, ma, ad esempio, ho un'intestazione che mostra l'indirizzo email dell'utente anche su rotte non sorvegliate. – Andrew

+0

Inoltre, questo non sembra funzionare, poiché il metodo 'canActivate()' deve restituire 'Observable | booleano', ma nel tuo esempio non restituisce nulla. Come posso risolverlo? – Andrew

+0

Siamo spiacenti, ho dimenticato di restituire un risultato in canActivate. – Baumi

6

potrebbe essere diverso in alcune versioni del router, ma avevo bisogno di restituire un osservabile che completa .

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

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

    canActivate(): Observable<boolean> { 
    return this.af.auth.map(user => { 
     if (user != null) 
     return true 
     this.router.navigate(['/login']) 
    }) 
    .take(1) // To make the observable complete after the first emission 
    } 
} 
Problemi correlati