我正在使用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}一切都被初始化后返回一个布尔值?
答案 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;
}
});
}
EDIT
An other option is to use bindCallback
to create an observable from the callback and perform a map just like my example.