Angular 2 AuthGuard with Firebase Auth 每次都重定向到登录页面

Angular 2 AuthGuard with Firebase Auth redirects each time to SignIn page

我正在尝试使用 firebase-auth 为 Angular 2 应用程序构建 AuthGuard,但存在一个问题。

应用程序加载后如果我因为异步操作而在 AuthGuard returns false 中签名。

最终效果是当页面首先加载 AuthGuard returns 时 false 然后 true,所以每次都重定向到登录页面而不是根页面。

我认为我使用 *ngIf 仅显示 SignInComponent,如果用户未登录,但这不是解决方案,因为每次 SignInComponent 都会在短时间内可见。

如何解决这个问题不立即重定向到登录页面?

谢谢您的回答。

AuthService

@Injectable()
export class AuthService {

  static UNKNOWN_USER = new AuthInfo(null);
  user: Observable<firebase.User>;
  authInfo$: BehaviorSubject<AuthInfo> = new BehaviorSubject<AuthInfo>(AuthService.UNKNOWN_USER);

  constructor(private afAuth: AngularFireAuth) {
    this.afAuth.authState.subscribe(
      auth => {
        if (auth) {
          const authInfo = new AuthInfo(auth.uid);
          this.authInfo$.next(authInfo);
        } else {
          this.authInfo$.next(AuthService.UNKNOWN_USER);
        }
      },
      err => {
        console.log(err);
      }
    );
  }
}

AuthInfo

export class AuthInfo {
  constructor(
    public $uid: string
  ) {

  }

  isLoggedIn() {
    return !!this.$uid;
  }
}

AuthGuard

@Injectable()
export class AuthGuard implements  CanActivate {

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

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    return this.authService.authInfo$
      .map( authInfo => authInfo.isLoggedIn())
      .take(1)
      .do(allowed => {
        console.log('authguard: ' + allowed);
        if (!allowed) {
           this.router.navigate(['/signin']);
        }
    });
  }
}

抱歉,这是

的重复问题

我的解决方案是

AuthService

@Injectable()
export class AuthService {

  static UNKNOWN_USER = new AuthInfo(null);
  authInfo$: BehaviorSubject<AuthInfo> = new BehaviorSubject<AuthInfo>(AuthService.UNKNOWN_USER);

  constructor(private afAuth: AngularFireAuth) {}

  getAuthInfo(): Observable<AuthInfo> {
    return this.afAuth.authState.map(
      auth => {
        if (auth) {
          const authInfo = new AuthInfo(auth.uid);
          this.authInfo$.next(authInfo);
          return authInfo;
        } else {
          this.authInfo$.next(AuthService.UNKNOWN_USER);
          return AuthService.UNKNOWN_USER;
        }
      },
      err => {
        console.log(err);
      }
    );
  }

AuthGuard

@Injectable()
export class AuthGuard implements  CanActivate {

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

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {

    if (this.authService.authInfo$.getValue().isLoggedIn()) {
      return true;
    }

    return this.authService.getAuthInfo()
      .map( (authInfo: AuthInfo) => authInfo.isLoggedIn())
      .do(allowed => {
        if (!allowed) {
          this.router.navigate(['/signin']);
          return false;
        } else {
          return true;
        }
      }).take(1);
  }
}