【问题标题】:Angular 2 AuthGuard + Firebase AuthAngular 2 AuthGuard + Firebase 身份验证
【发布时间】:2017-01-22 06:22:06
【问题描述】:

我正在尝试使用 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 以返回一个 observable。

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);

【问题讨论】:

  • 嗨!你能做一个 plunkr 吗?
  • @GuillaumeLeMière 这将非常困难,因为涉及到 Firebase 身份验证......

标签: angular typescript firebase firebase-authentication angularfire2


【解决方案1】:

使用 .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);
  }

【讨论】:

  • 升级到 Angular 2.0.0 后,我似乎无法再使用 map()。 Ts 说Property 'map' does not exist in type 'AngularFireAuth'
  • 我必须添加 import 'rxjs/add/operator/map' 和 import 'rxjs/add/operator/take' 才能使其工作,但它毕竟工作。谢谢!
  • 很高兴它对你有用。我应该提到导入,因为从 RC5 升级后我遇到了同样的问题。
  • 对我不起作用。我不断收到错误:error TS2322: Type 'Observable<boolean>' is not assignable to type 'boolean'. 我的问题在这里:stackoverflow.com/questions/39687114/…
  • 我添加了所需的rxjs相关导入语句
【解决方案2】:

对于较新版本的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

【讨论】:

  • 你拯救了我的一天 :)
【解决方案3】:

已经用 Angular 11 和 Angular Fire 6 测试过这个

canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.afAuth.authState.pipe(
  map(authState => !!authState),
  map(auth => {
    if (!auth) {
      this.router.navigate(['/sign-in']);
    }
    return auth;
  }),
 );
}

【讨论】:

    猜你喜欢
    • 2017-02-24
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 2018-04-15
    • 2020-06-01
    • 1970-01-01
    • 2020-05-20
    • 2020-08-13
    相关资源
    最近更新 更多