使用火基和角度进行身份验证.用户登录后如何导航到其他组件?



我想在Firebase的帮助下验证一个用Angular编写的网站。
我找到了一个指南,详细而清晰地描述了如何做到这一点。
网址: https://www.positronx.io/full-angular-7-firebase-authentication-system/
指南附加的 github:https://github.com/SinghDigamber/angularfirebase-authentication

我按照说明进行操作,但在用户登录后没有成功导航到其他组件(用户保持在同一页面上(。 当我从github运行代码时,我遇到了同样的问题。

来自auth.service.ts的部分代码:

// Sign in with email/password
SignIn(email, password) {
alert(":)");
return this.afAuth.signInWithEmailAndPassword(email, password)
.then((result) => {
this.ngZone.run(() => {
this.router.navigate(['/dashboard']);
});
this.SetUserData(result.user);
}).catch((error) => {
window.alert(error.message)
})
}

为什么用户在登录后没有导航到仪表板组件?

问题的原因可能是什么?谢谢。

编辑: 我将在这里添加我认为相关的代码:auth.service.ts:

import { Injectable, NgZone } from '@angular/core';
//import { User } from "../services/user";
//import { auth } from 'firebase/app';
import { AngularFireAuth } from "@angular/fire/auth";
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';
import { Router } from "@angular/router";
export interface User {
email: string;
} 
@Injectable({
providedIn: 'root'
})
export class AuthService {
userData: any; // Save logged in user data
authStateSubs: any;
//authStateSubs: any;
constructor(
public afs: AngularFirestore,   // Inject Firestore service
public afAuth: AngularFireAuth, // Inject Firebase auth service
public router: Router,
public auth: AngularFireAuth,  
public ngZone: NgZone // NgZone service to remove outside scope warning
) {
/* Saving user data in localstorage when 
logged in and setting up null when logged out */
this.afAuth.authState.subscribe(user => {
if (user) {
this.userData = user;
localStorage.setItem('user', JSON.stringify(this.userData));
JSON.parse(localStorage.getItem('user'));
} else {
localStorage.setItem('user', null);
JSON.parse(localStorage.getItem('user'));
}
})
}
// Sign in with email/password
SignIn(email, password) {
return this.afAuth.signInWithEmailAndPassword(email, password)
.then((result) => {
alert("after signInWithEmailAndPassword");
this.ngZone.run(() => {
alert("after ngZone.run");
this.router.navigate(['/authorized-zone']);
});
this.SetUserData(result.user);
}).catch((error) => {
window.alert(error.message)
})
}

// Returns true when user is looged in and email is verified
get isLoggedIn(): boolean {
const user = JSON.parse(localStorage.getItem('user'));
return (user !== null && user.emailVerified !== false) ? true : false;
}

/* Setting up user data when sign in with username/password, 
sign up with username/password and sign in with social auth  
provider in Firestore database using AngularFirestore + AngularFirestoreDocument service */
SetUserData(user) {
const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.email}`);
const userData: User = {
email: user.email,
}
return userRef.set(userData, {
merge: true
})
}
// Sign out 
SignOut() {
return this.afAuth.signOut().then(() => {
localStorage.removeItem('user');
this.router.navigate(['login']);
})
}
}

auth.guard.ts:

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { AuthService } from "../services/auth.service";
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(
public authService: AuthService,
public router: Router
){ }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if(this.authService.isLoggedIn !== true) {
this.router.navigate(['login'])
}
return true;
}
}

如果要基于登录和注销执行某些操作,一种简单而好的方法是使用对 authState 的订阅。在服务的蟒蛇中执行此操作。 然后,您无需在登录电子邮件和密码中执行任何操作。

constructor(
public auth: AngularFireAuth,
private router: Router,
//... 
){
this.authStateSubs=this.auth.authState.subscribe(fbUser=>{
//this is a Sign in. 
if( fbUser && fbUser.uid){ 
this.router.navigate(['/wherever_you_want']);
}else{
//Sign out. Go to sign-in page. 
}
});
}

我认为在导航之前必须将用户数据保存在本地存储中。

this.ngZone.run(() => {
alert("after ngZone.run");
localStorage.setItem('user', JSON.stringify(result.user));
this.router.navigate(['/authorized-zone']);
});

否则,本地存储为空,并在导航时受到保护。

您可以尝试等待带有承诺的导航结果,也许它永远不会发生

this.router.navigate(['dashboard']).then(succeeded => {
this.SetUserData(result.user);
});

您可以使用 async/await 来简化承诺代码,例如

async signIn(email, password) {
alert(":)");
const result = await this.afAuth.signInWithEmailAndPassword(email, password);
const succeeded = await this.router.navigate(['dashboard']);
if (succeeded) {
this.SetUserData(result.user);
}
}

尝试分叉这些示例并将environment.ts替换为您自己的设置并测试其工作原理

最新更新