Açısal 2 - Yönlendirme - Gözlemlenebilir ile çalışmayı etkinleştirebilir


94

Bir sahip AuthGuard uygular ki (yönlendirmek için kullanılır) CanActivate .

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

Benim sorunum, CanActivate-sonucunun bir http-get-sonucuna bağlı olması - LoginService bir Observable döndürüyor .

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

Bunları nasıl bir araya getirebilirim - CanActivate'i arka uç durumuna bağlı hale getirebilirim?

# # # # # #

DÜZENLEME: Lütfen bu sorunun 2016 yılına ait olduğunu unutmayın - açısal / yönlendiricinin çok erken bir aşaması kullanılmıştır.

# # # # # #


2
Burayı okudun mu angular.io/docs/ts/latest/guide/router.html İşte Rota Muhafızlar arayışları CanActivate için API referanstır: angular.io/docs/ts/latest/api/router/index/... bunu ya dönebilirsiniz gördüğünüz gibi boole veya Gözlemlenebilir <boolean>
mollwe

4
canActivate()bir döndürebilir Observable, sadece Observabletamamlandığından emin olun (yani. observer.complete()).
Philip Bulley

1
@PhilipBulley ya gözlemlenebilir daha fazla değer yayarsa ve sonra tamamlarsa? Muhafız ne yapar? Şimdiye kadar gördüğüm take(1)şey, akışın eksiksiz olmasını sağlamak için Rx operatörünün kullanılmasıdır , Ya eklemeyi unutursam?
Felix

Yanıtlar:


146

"@ Angular / router" ı en son sürüme yükseltmelisiniz. ör. "3.0.0-alpha.8"

AuthGuard.ts değiştir

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

Herhangi bir sorunuz varsa bana sorun!


3
Bunun vaatlerle çok benzer şekilde çalıştığını belirtmekte fayda var. Benim uygulamam için, bir varsayarsak isLoggedIn(), Promiseyapabilirsiniz isLoggedIn().then((e) => { if (e) { return true; } }).catch(() => { return false; });Umarım bu, gelecekteki gezginlere yardımcı olur!
kbpontius

6
Eklemek zorunda kaldımimport 'rxjs/add/observable/of';
marc_aragones

1
şimdi iyi bir cevap değil IMO .. sunucu tarafında neler olduğuna dair hiçbir detay vermiyor ... alpha'da güncel değil! ... bu en iyi uygulamayı takip etmiyor .. angular.io/docs/ts/latest/guide/… .. aşağıdaki güncellenmiş
cevabıma

1
canActivate, Observable <boolean> öğesini yeniden çalıştırmalı
Yoav Schniederman

Great Help :) Teşekkürler
gschambial

57

Açısal 5 ve RxJS 5.5 için Kery Hu'nun cevabı Güncellenmesi operatör kullanımdan kaldırıldı. Şimdi catchError operatörünü boru ve izin verilebilir operatörlerle birlikte kullanmalısınız .catch

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

}

İsLoggedIn () 'den sonra 1 tane daha XHR çağrım var ve XHR'nin sonucu 2. XHR çağrısında kullanılıyor. 1. sonucu kabul edecek 2. ajax çağrısı nasıl yapılır? Verdiğiniz örnek oldukça kolay, eğer bende başka bir ajax varsa, pipe () 'yı nasıl kullanacağımı bana söyler misiniz?
Pratik

9

canActivate () kabul ederObservable<boolean> döndürülen değer olarak . Koruma, Gözlemlenebilir'in çözülmesini ve değere bakmasını bekleyecektir. "Doğru" ise, kontrolü geçecektir, aksi takdirde (herhangi bir başka veri veya atılan hata) yolu reddedecektir.

Sen kullanabilirsiniz .mapdönüştürmeye operatörü Observable<Response>için Observable<boolean>şöyle:

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

1
peki ya bir yakalama bloğu? catch bloğu bir 401 doğruysa çağrılır?
danday74

1
Açısal 4'te çalışmıyor. Genel bir tür tanımlamak için bir yere ihtiyacı var.
gtzinos

2

Bunu şu şekilde yaptım:

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

Gördüğünüz gibi userService.auth'a http araması başarısız olursa ne yapacağımı bir geri dönüş işlevi gönderiyorum.

Ve userService'te:

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

.map () işlevi açısından gerçekten iyi bir cevap - gerçekten çok iyi :) - geri dönüş geri çağrısını kullanmadım - bunun yerine canActivate yönteminde Auth Observable'a abone oldum - fikir için çok teşekkürler
danday74

0

Bu sana yardımcı olabilir

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { Select } from '@ngxs/store';
import { Observable } from 'rxjs';
import { map, take } from 'rxjs/operators';
import { AuthState } from 'src/app/shared/state';

export const ROLE_SUPER = 'ROLE_SUPER';

@Injectable()
export class AdminGuard implements CanActivate {

 @Select(AuthState.userRole)
  private userRoles$: Observable<string[]>;

  constructor(private router: Router) {}

 /**
   * @description Checks the user role and navigate based on it
   */

 canActivate(): Observable<boolean> {
    return this.userRoles$.pipe(
      take(1),
      map(userRole => {
        console.log(userRole);
        if (!userRole) {
          return false;
        }
        if (userRole.indexOf(ROLE_SUPER) > -1) {
          return true;
        } else {
          this.router.navigate(['/login']);
        }
        return false;
      })
    );
  } // canActivate()
} // class

-1

CanActivate, Observable ile çalışır, ancak CanActivate: [Guard1, Guard2] gibi 2 çağrı yapıldığında başarısız olur.
Burada, Guard1'den bir Observable of false döndürürseniz, Guard2'de de kontrol edecek ve Guard2 true dönerse rotaya erişime izin verecektir. Bundan kaçınmak için, Guard1, Observable yerine Boolean yerine bir boole döndürmelidir.


-10

canActivate () 'de yerel bir boole özelliği döndürebilirsiniz (sizin durumunuzda varsayılan olarak false).

private _canActivate: boolean = false;
canActivate() {
  return this._canActivate;
}

Ve sonra LoginService sonucunda, o özelliğin değerini değiştirebilirsiniz.

//...
this.loginService.login().subscribe(success => this._canActivate = true);

siz bir dahisiniz efendim.
Kien Nguyen Ngoc
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.