如何将 AngularFire2 身份验证作为可观察的?

How to get AngularFire2 authentication as an observable?

我想在身份验证后将 isAuthenticated:boolean 设置为 True 在成功联合 Google 登录后,或者用户处于登录状态。

import {Injectable} from '@angular/core';
import {AngularFire} from 'angularfire2';
import {Observable} from 'rxjs/Observable';


//this current code is not making sense. Any suggestion 
//to make it an Observable for Signin and Logout?
@Injectable()
export class AuthService {
  isAuthenticated:boolean = false;
  authObj: Observable<any>;

  constructor(public af:AngularFire) {
    this.authObj = af.auth;
  }

  signin() {
    //I want to make AngularFire2 Authentication token/obj an Observable. So this will keep emitting an Observable
    //that return True.... after successful Federated Google Signin. I want my other component to subscribe to this Observable.
    return this.authObj.do(val => this.af.auth.login());
    this.isAuthenticated = true;
  }

}

只需订阅 auth 对象即可在有或没有用户对象时得到通知...

  var auth = this.af.auth.subscribe( (user) => {
    debugger;
    if (user) {
      // User signed in!
      var uid = user.uid;
      console.log(uid)
    } else {
      // User logged out
      console.log("no user")
    }
  });

我写了一篇文章,把零碎的东西拼凑在一起。您可能需要像这样创建身份验证服务:

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/first';
import { Observable } from 'rxjs/Observable';

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AngularFire } from 'angularfire2';

@Injectable()
export class AuthGuard implements CanActivate{
  public allowed: boolean;

  constructor(private af: AngularFire, private router: Router) { }

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

查看 AngularFire2 Authentication article 了解更多信息。

使用 Angular v6Firebase v5.0.*angularfire2 5 rc 10 你可以做这样的事情。

...
import { AngularFireAuth } from 'angularfire2/auth';
import { map } from 'rxjs/operators';

...
export class DashboardGuard implements CanActivate, CanActivateChild {

  constructor(private router: Router, private auth: AngularFireAuth) { }
  // #2
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    // #1
    return this.auth.authState.pipe(
      // #3
      map((user: any) => user !== null) // <--- [1]
    );

  }

  canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.canActivate(route, state);
  }

}

直接使用 AngularFireAuthauthState 将其通过管道传输并检查用户是否不等于 null [1].

  1. authState returns Observable<firebase.User>
  2. canActivate() returns Observable<boolean> | Promise<boolean> | boolean
  3. 订阅 authState 将发出 null 如果未通过身份验证,否则会发出 firebase.User(请参见下面的屏幕截图)。

我刚刚发现我现在可以使用最新版本来做到这一点 -> return canActivate 中的 Observable<boolean>... 因为在最新版本中虽然在文档说 canActivate returns Observable<boolean> 它给了我很多错误。但现在是的!

顺便说一句,我只是想分享一下我在 angular v6 之前是如何编写路由守卫的。使用承诺

constructor(private router: Router, private afAuth: AngularFireAuth) {}

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  const promise = new Promise(
    (resolve, reject) => {
      this.afAuth.authState.subscribe((state: any) => {
        resolve(state !== null);
      });
    }
  );

  return promise.then((data: boolean) => {
    if (data) {
      return data;
    } else {
      this.router.navigate(['/']);
    }
  });
}