119 votes

Angulaire 2 - Routage - CanActivate travailler avec Observables

J'ai un AuthGuard (utilisé pour le routage) qui implémente CanActivate.

canActivate() {
    return this.loginService.isLoggedIn();
}

Mon problème, c'est que le CanActivate-résultat dépend d'un http-get-résultat - le LoginService renvoie une Observable.

isLoggedIn():Observable<boolean> {
    return this.http.get(ApiResources.LOGON).map(response => response.ok);
}

Comment puis-je apporter à ceux - faites CanActivate dépendent d'un backend de l'état?

168voto

Kery Hu Points 1641

Vous devez mettre à niveau "@angulaire/routeur" à la dernière . par exemple,"3.0.0-alpha.8"

modifier AuthGuard.ts

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

    canActivate(next:ActivatedRouteSnapshot, state:RouterStateSnapshot) {
        return this.loginService.isLoggedIn().map(e => {
            if (e) {
                return true;
            }
        }).catch(() => {
            this.router.navigate(['/login']);
            return Observable.of(false);
        });
    }   
}

Si vous avez des questions, posez-les moi!

92voto

Derek Hill Points 613

La mise à jour de Kery Hu réponse Angulaire 5 et RxJS 5.5 où l' catch opérateur est obsolète. Vous devez maintenant utiliser la catchError opérateur en conjonction avec de la pipe et locative des opérateurs.

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { catchError, map} from 'rxjs/operators';
import { of } from 'rxjs/observable/of';

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private loginService: LoginService, private router: Router) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>  {
    return this.loginService.isLoggedIn().pipe(
      map(e => {
        if (e) {
          return true;
        } else {
          ...
        }
      }),
      catchError((err) => {
        this.router.navigate(['/login']);
        return of(false);
      })
    );
  }   

}

15voto

mp3por Points 866

canActivate() accepte Observable<boolean> comme valeur de retour. Le garde va attendre le Observables pour résoudre et regardez la valeur. Si le "vrai" il va passer de la case, sinon ( toutes les autres données ou jetés erreur ) rejettera la route.

Vous pouvez utiliser l' .map opérateur de transformer l' Observable<Response> de Observable<boolean> comme:

canActivate(){
    return this.http.login().map((res: Response)=>{
       if ( res.status === 200 ) return true;
       return false;
    });
}

3voto

Je l'ai fait de cette façon:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.userService.auth(() => this.router.navigate(['/user/sign-in']));}

Comme vous pouvez le voir je suis de l'envoi d'un repli de la fonction de userService.auth que faire si http échec de l'appel.

Et dans userService j'ai:

import 'rxjs/add/observable/of';

auth(fallback): Observable<boolean> {
return this.http.get(environment.API_URL + '/user/profile', { withCredentials: true })
  .map(() => true).catch(() => {
    fallback();
    return Observable.of(false);
  });}

0voto

Paresh Trivedi Points 1

Comment cela fonctionne pour vous, sans faire appel à vous abonner? pour moi quand je l'appelle par mon .net API rien est de retour. J'ai appeler abonnez-vous sur mon auth service de garde comme ce alors seulement il rend réel les appels de l'API. Mais depuis abonnez-vous est asynchrone mon canActivate garde ne fonctionne pas et l'utilisateur peut entrer dans la page.

AuthGauard service:

canActivate() { this.loginService.isLoggedIn()
      .subscribe(response => {
          if (!response) return false;})
return true;
}

loginService:
    isLoggedIn():Observable<boolean> {
        return this.http.get(ApiResources.LOGON).pipe(map(response => response.ok));
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X