Angular2 - 基于角色的AuthGuard

时间:2016-10-18 17:54:12

标签: angular rxjs

我的目标是实施一个AuthGuard,用于检查用户是否可以根据他们的角色和请求的路由访问特定路由,如果他们具有正确的路由角色,则允许他们继续,或者如果他们具有相应的角色,则将其重定向到其他地方不要。

AuthGuard调用我的AuthorizationService,它返回一个Observable(UserRole)。我无法评估用户的observable并将值返回给canActivate。这肯定与我对RxJS Observables的经验不足有关,但我似乎无法超越这一点。

我有 auth.guard.service.ts

 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {        

        let url: string = state.url;

        var currentUser$ = this.authService.getCurrentUser();

        currentUser$.subscribe((currentUser: MyUser) => {    

            if (currentUser.isInternalUser && url === '/internal') {
                console.debug("Internal User! Yes");
                this.router.navigate(['/internal']);
                return true;
            } else if (currentUser.isExternalUser && url === '/dashboard') {
                console.debug("External User! Yes");                    
                this.router.navigate(['/external']);
                return true;
            } else {
                console.debug("Access Denied...");
                this.router.navigate(['/pagenotfound']);
                return false;
            }
        });

       //return Observable.of(false);  // I need to return something, but this is not what I want to return!!

    }

auth.service.ts

 getCurrentUser() : Observable<MyUser> {

        let currentUser$: Observable<MyUser>;

        currentUser$ = this.http.get(this.location.prepareExternalUrl('api/v1/userprofile/')) 
            .cache()       
            .map(this.extractData)
            .catch(this.handleError);

        console.log("AuthService#getCurrentUser being called.");

        return currentUser$;
    }

如何评估我的currentUser并让 canActivate 返回一个boolean observable?

1 个答案:

答案 0 :(得分:3)

您需要在订阅之前返回Observable。订阅是一个终端操作,通知Observable它现在已连接,并且它可以开始将事件推送到订阅者(由您传递给订阅函数的处理程序表示)。

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot
): Observable<boolean> {
   const url: string = state.url;
   return this.authService.getCurrentUser()
     .flatMap(({isInternalUser, isExternalUser}: MyUser) => {
       if (isInternalUser && url === '/internal') {
         return Observable.fromPromise(this.router.navigate(['/internal']))
           .mapTo(true);
       } else if (isExternalUser && url === '/dashboard') {
         return Observable.fromPromise(this.router.navigate(['/external']))
           .mapTo(true);
       } else {
         return Observable.fromPromise(this.router.navigate(['/pagenotfound']))
           .mapTo(false);
       }
     });        
}

以上是您提供的代码的天真重构。恐怕我对Angular2的了解不足以告诉你这是不是你应该如何实现一个Auth Guard(尽管我会说,重新定向在表面上只是检查一下似乎有点奇怪是否该页面是否可访问。)

另外在旁注中,cache正在从RxJS 5的最终版本中删除,因此如果您计划升级,可能需要避免使用它。