web-dev-qa-db-ja.com

Angular 2-ルーティング-CanActivateはObservableで動作します

CanGuardateを実装するAuthGuard(ルーティングに使用)があります。

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

私の問題は、CanActivate-resultがhttp-get-resultに依存していることです。-LoginServiceObservableを返します。

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

それらをどのようにまとめることができますか-CanActivateをバックエンドの状態に依存させますか?

67
Philipp

「@ angular/router」を最新のものにアップグレードする必要があります。例:「3.0.0-alpha.8」

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

ご質問があれば、私に尋ねてください!

115
Kery Hu

Angular 5およびRxJS 5.5 に対するKery Huの回答を更新します。ここでcatchname__演算子は非推奨です。これで、catchError演算子をpipe および lettable演算子 と組み合わせて使用​​する必要があります。

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

}
33
Derek Hill

canActivate() は、戻り値としてObservable<boolean>を受け入れます。ガードはObservableが解決して値を確認するまで待機します。 'true'の場合、チェックに合格します。それ以外の場合(その他のデータまたはスローされたエラー)はルートを拒否します。

.map演算子を使用して、次のようにObservable<Response>Observable<boolean>に変換できます。

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

私はこの方法でそれをやった:

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

ご覧のとおり、http呼び出しが失敗した場合の対処方法をフォールバック関数をuserService.authに送信しています。

そして、userServiceには次のものがあります:

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

これはあなたを助けるかもしれません

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
Kalanka

サブスクライブを呼び出さずにどのように機能しますか? .net APIを通じてこれを呼び出すと、何も返されません。このように認証ガードサービスでサブスクライブを呼び出す必要があり、それから実際のAPI呼び出しのみを行います。しかし、サブスクライブは非同期なので、私のcanActivateガードは機能せず、ユーザーはページに入ることができます。

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));
    }
0
Paresh Trivedi