Angular 6 AngularFireAuth检查在呈现页面之前用户是否已登录 [英] Angular 6 AngularFireAuth check if user is logged in before page rendered

查看:72
本文介绍了Angular 6 AngularFireAuth检查在呈现页面之前用户是否已登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用Firebase身份验证和Cloud Fire Store建立了一个新的angular 6项目.有一个登录页面,您可以在其中通过Google登录,并将用户数据保存在Firestore中(以下代码).我唯一的问题是如何检查用户是否已经登录,是否有最佳实践?

I have set up a new angular 6 project with Firebase auth and Cloud Fire Store. There is a login page where you can login via google and the user data is saved in Firestore (code below). My only issue is how I can check if the user is already logged in, is there any best practice?

目前,我正在异步获取用户数据,但随后导航闪烁.一秒钟有一个登录按钮,然后切换到注销按钮.有没有好的方法可以在登录页面呈现之前检查登录状态?

At the moment im fetching the user data async, but then the navigation is flickering. For one second there is the login button, then it switches to the logout button. Is there good way to check the login state before it renders the page?

User.ts

User.ts

export interface User {
  uid: string;
  email: string;
}

auth.service.ts

auth.service.ts

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import * as firebase from 'firebase/app';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFirestore, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { User } from './user';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  user: Observable<User>;

  constructor(private afAuth: AngularFireAuth, private afs: AngularFirestore, private router: Router) {
    this.user = this.afAuth.authState.pipe(
        switchMap(user => {
          if (user) {
            return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
          } else {
            return of(null);
          }
        }))
  }

  public googleLogin() {
    const provider = new firebase.auth.GoogleAuthProvider()
    return this.oAuthLogin(provider);
  }

  public signOut() {
    this.afAuth.auth.signOut();
  }

  private oAuthLogin(provider) {
    return this.afAuth.auth.signInWithPopup(provider)
      .then((credential) => {
        this.updateUserData(credential.user)
      })
  }

  private updateUserData(user) {
    const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.uid}`);
    const data: User = {
      uid: user.uid,
      email: user.email
    }
    return userRef.set(data, { merge: true })
  }

}

navigation.component.ts

navigation.component.ts

import { Component, OnInit } from '@angular/core';
import { AuthService } from '../core/auth.service';
import { AngularFireAuth } from 'angularfire2/auth';

@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.scss']
})
export class NavigationComponent implements OnInit {

  constructor(public auth: AuthService) { }

  ngOnInit() {}

}

auth.service.ts

auth.service.ts

<div *ngIf="auth.user | async; then loggedIn else loggedOut"></div>
                    
<ng-template #loggedOut>
    <li  class="nav-item d-none d-md-inline-block pl-2 pr-0">
        <a class="btn btn-sm btn-primary u-btn-primary u-btn-pill transition-3d-hover" href="/login">
            Login
        </a>
    </li>
</ng-template>

<ng-template #loggedIn>
    <li  class="nav-item d-none d-md-inline-block pl-2 pr-0">
        <a class="btn btn-sm btn-primary u-btn-primary u-btn-pill transition-3d-hover" (click)="auth.signOut()">
            Logout
        </a>
    </li>
</ng-template>

推荐答案

您可能很久以前就已经知道了这一点,但是其他人可能会感到奇怪.我选择对angularFireAuth的authState进行检查.如果为空,则您已注销.然后,您可以按照 Ryan Chenkie的中型文章

You probably figured this out a long time ago but someone else might wonder. I chose to do a check against the authState of angularFireAuth. If it's null, then you're logged out. Then You can use route guards as explained in Ryan Chenkie's Medium article

@Injectable()
export class FirebaseAuthService {
private authState: Observable<firebase.User>
private currentUser: firebase.User = null;

constructor(
  public afAuth: AngularFireAuth,
  private http: HttpClient,
  private localStorage: LocalStorageService,
  private router: Router,
  private snackBar: MatSnackBar) {
  this.authState = this.afAuth.authState;

this.authState.subscribe(user => {
  if (user) {
    this.currentUser = user;
    this.localStorage.storeSimple('userData', user)
    this.openSnackBar('Successfully authenticated');
    console.log('AUTHSTATE USER', user)
    this.router.navigate(['home']);
  } else {
    console.log('AUTHSTATE USER EMPTY', user)
    this.currentUser = null;
  }
},
  err => {
    this.openSnackBar(`${err.status} ${err.statusText} (${err.error.message})`, 'Please try again')
  });
 }

 isAuthenticated(): boolean {
   return this.authState !== null;
 }

 loginEmail(email, password, route) {
   this.afAuth.auth.signInWithEmailAndPassword(email, password).catch(error => {
   let errorCode = error.code;
   let errorMessage = error.message;
   this.openSnackBar(error, 'OK')
 });
}

logout() {
  this.afAuth.auth.signOut()
  .then(response => this.openSnackBar('Signed out'))
  .catch(error => this.openSnackBar('Error signing out: ' + error));
}

...
}

这篇关于Angular 6 AngularFireAuth检查在呈现页面之前用户是否已登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆