Angular CanActivate与Firebase后端

时间:2017-05-16 08:32:15

标签: angular firebase firebase-authentication

我正在使用Firebase后端开发一个Angular应用。启动时,应用程序需要检查用户当前是否已登录;如果用户登录应用程序应导航到主页,如果用户未登录应用程序,则应导航到登录页面。

我想在canActivate路由定义中使用单AuthGuard Home来实现此目的,即

const homeRoutes: Routes = [
  {
    path: 'home',
    component: HomeComponent,
    canActivate: [AuthGuard]
  }
]

其中AuthGuard实现canActivate如下

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate() {
    // Need to work out what goes here
  }
}

现在Firebase提供了可观察的onAuthStateChanged(请参阅here),我可以使用它来确定用户当前是否已登录,并且假设canActivate可以返回布尔值可观察的,我可以写下我的AuthGuard如下

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private firebaseService: Firebase, private router: Router){}

  canActivate() {

      return Observable.create(obs => {
          this.firebaseService.onAuthStateChanged(user => {
              if (user) {
                 obs.next(true);
              }
              else {
                 obs.next(false);
                 router.navigate(['login']);
              }
          });
   }
}

当我启动未登录的应用程序时,这似乎有效,即我已定向到登录页面。但是,现在当我成功登录应用程序尝试导航到home时,在canActivate上调用AuthGuard但此时似乎停止,即我仍然在登录页面上。我认为这是因为我正在返回一个observable并且状态在调用canActivate之前已经发生了变化,因此没有任何内容告诉canActivate它可以显示home页面。

是否有一种干净的方法来处理我需要canActivate在启动时返回一个observable的情况,以确保Firebase已经初始化,然后我才确定它们是否已经登录,但是后来{{1}一切都被初始化后返回一个布尔值?

1 个答案:

答案 0 :(得分:1)

I switched to AngularFire2 which makes this easier:

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    return this.af.authState.map(auth => {
      if (isNullOrUndefined(auth)) {
        this.router.navigate(['/login']);
        return false;
      } else {
        return true;
      }
    });
  }

Check this out

EDIT

An other option is to use bindCallback to create an observable from the callback and perform a map just like my example.