Program Tip

Angular 2-라우팅-Observable로 CanActivate 작업

programtip 2020. 10. 23. 08:22
반응형

Angular 2-라우팅-Observable로 CanActivate 작업


나는이 AuthGuard 가 구현 (라우팅에 사용) CanActivate을 .

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

내 문제는 CanActivate-결과가 HTTP-GET-결과에 달려 있다는합니다 - LoginService를 다시 표시 관찰 가능한 .

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

그것들을 어떻게 모을 수 있습니까? CanActivate가 백엔드 상태에 의존하도록 만들 수 있습니까?


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

궁금한 점이 있으면 물어보세요!


각도 5 RxJS 5.5 Kery 후의 대답 업데이트 연산자는 사용되지 않습니다를. 이제 pipelettable 연산자 와 함께 catchError 연산자를 사용해야합니다 .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);
      })
    );
  }   

}

canActivate ()Observable<boolean>반환 된 값으로 받아들 입니다. 경비원은 Observable이 해결되고 값을 볼 때까지 기다릴 것입니다. 'true'이면 검사를 통과하고, 그렇지 않으면 (다른 데이터 또는 throw 된 오류) 경로를 거부합니다.

당신은 사용할 수 있습니다 .map를 변환 연산자 Observable<Response>Observable<boolean>이렇게 같은 :

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

나는 이런 식으로 그것을했다 :

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

구독을 요청하지 않고 어떻게 작동합니까? 내 .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));
    }

CanActivate does work with Observable but fails when 2 calls are made like CanActivate:[Guard1, Guard2].
Here if you return an Observable of false from Guard1 then too it will check in Guard2 and allow access to route if Guard2 returns true. In order to avoid that, Guard1 should return a boolean instead of Observable of boolean.


in canActivate(), you can return a local boolean property (default to false in your case).

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

And then in the result of the LoginService, you can modify the value of that property.

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

참고URL : https://stackoverflow.com/questions/37948068/angular-2-routing-canactivate-work-with-observable

반응형