首页 文章

Angular 2 AuthGuard Firebase Auth

提问于
浏览
20

我正在尝试使用Firebase Auth为Angular 2路由构建一个AuthGuard .

这是AuthGuard服务:

import { Injectable }             from '@angular/core';
import { CanActivate, Router,
         ActivatedRouteSnapshot,
         RouterStateSnapshot }    from '@angular/router';
import { AuthService }            from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private AuthService: AuthService, 
                private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (this.AuthService.loggedIn) { return true; }

    this.router.navigate(['login']);
    return false;
  }
}

这是AuthService,它检查用户是否登录并将结果绑定到其构造函数中的“loggedIn”属性 .

import { Injectable } from '@angular/core';
import { AngularFire } from 'angularfire2';
import { Router } from '@angular/router';

@Injectable()
export class AuthService {
loggedIn: boolean = false;

  constructor(
    public af: AngularFire,
    public router: Router) {
        af.auth.subscribe(user => {
            if(user){
                this.loggedIn = true;
            }
        });
    }
}

这里的问题显然是异步的 . AuthGuard的canActivate()始终返回false值,因为订阅未及时收到数据以将'loggedIn'更改为true .

解决这个问题的最佳做法是什么?

编辑:

更改了AuthGuard以返回可观察的内容 .

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.af.auth.map((auth) => {
        if (!auth) {
          this.router.navigateByUrl('login');
          return false;
        }
        return true;
    });
  }

它有点工作,因为你没有被重定向到登录...但目标AuthGuarded组件不会被渲染 .

不确定它是否与我的app.routes有关 . 这是该部分的代码:

const routes: Routes = [
  { path: '', component: MainComponent, canActivate: [AuthGuard] },
  ...
];

export const routing = RouterModule.forRoot(routes);

2 回答

  • 11

    使用.take(1)完成observable以使组件渲染 .

    import {Observable} from "rxjs/Observable";
    import 'rxjs/add/operator/map';
    import 'rxjs/add/operator/take';
    
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        return this.af.auth.map((auth) => {
            if (!auth) {
              this.router.navigateByUrl('login');
              return false;
            }
            return true;
        }).take(1);
      }
    
  • 6

    对于较新版本的 AngularFire ,您必须使用 authState 代替:

    @Injectable()
    export class AuthGuard implements CanActivate {
      constructor(
        private afAuth: AngularFireAuth,
        private router: Router
      ) {}
    
      canActivate(): Observable<boolean> {
        return this.afAuth.authState
          .take(1)
          .map(authState => !!authState)
          .do(auth => !auth ? this.router.navigate(['/login']) : true);
      }
    }
    

    不要忘记从 rxjs/add/operator 导入 takemapdo .

相关问题