Angular Firebase身份验证,如何检查用户是否已登录并隐藏导航中的登录链接?

3
我实现了Angular Firebase的电子邮件和密码注册登录,但现在我想要做的是在我的导航模板中检查用户的状态,如果用户已经登录,则隐藏登录按钮以及注册按钮。我试图通过谷歌搜索一些教程来解决这个问题,发现我必须使用AuthService和AuthInfo,如您在此处看到的:https://github.com/angular-university/angular-firebase-app/blob/master/src/app/shared/security/auth.service.ts。问题在于他们使用了很多Promise和其他东西,这让我感到很困惑。我正在尝试以最基本的方式实现这一点,并寻找有人指导和帮助我。以下是我的代码:
导航-
<ul class="nav navbar-nav">
    <li><a routerLink="" routerLinkActive="active">Home</a></li>
    <li><a routerLink="login" routerLinkActive="active" *ngIf="!authInfo?.isLoggedIn()">Login</a></li>
    <li><a routerLink="register" routerLinkActive="active" *ngIf="!authInfo?.isLoggedIn()">Register</a></li>
    <li><a routerLink="quiz" routerLinkActive="active">Quiz</a></li>
</ul>

认证服务文件中包含了所有用户创建和登录到Firebase的逻辑 -

@Injectable({
    providedIn: 'root'
})
export class AuthService {
    private user: Observable<firebase.User>;
    constructor(private _firebaseAuth: AngularFireAuth, private router: Router) {
        this.user = _firebaseAuth.authState;

        this.user.subscribe(
            (user) => {
                if (user) {
                    this.userDetails = user;

                    console.log(this.userDetails);
                } else {
                    this.userDetails = null;
                }
            }
        );
    }

    logUserIn(email, pass) {
        firebase.auth().signInWithEmailAndPassword(email, pass).catch(function (error) {
            // Handle Errors here.
            var errorCode = error.code;
            var errorMessage = error.message;
            console.log("error" + error);
        })

        if (this.userDetails) {
            email = this.userDetails.email;
            console.log("hello im user" + " " + email);

        } else {
            console.log("not working");
        }

        this.router.navigate(['']);
    }

    regUser(email, pass) {
        firebase.auth().createUserWithEmailAndPassword(email, pass)
            .catch(function (error) {
                // Handle Errors here.
                var errorCode = error.code;
                var errorMessage = error.message;

            });
    }
}

登录组件 -

@Component({
    selector: 'login',
    templateUrl: 'login.component.html'
})
export class LoginComponent {

    form: FormGroup;

    constructor(fb: FormBuilder, private _loginService: LoginService, private auth: AuthService) {

        this.form = fb.group({
            email: ['', Validators.required],
            password: ['', Validators.compose([Validators.required,
            PasswordValidator.cannotContainSpace])]
        })

    }

    login() {
        this.auth.logUserIn(this.form.value.email, this.form.value.password);
    };
}

从上面的github链接中获取auth-info.ts文件 -
export class AuthInfo {

    constructor(public $uid: string) { }

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

编辑:

感谢Tushar Walzade的帮助,我成功地显示和隐藏了这些按钮,但是我遇到了非常奇怪的行为。退出登录时没有问题,但是当我登录时,什么也不会发生,Chrome控制台中会出现“not working”消息,该消息来自于我的Auth服务的logUserIn方法。但是当我刷新页面一次后,它就会显示出正在工作,我可以在控制台中获得用户信息详细信息并且按钮被隐藏。我不知道为什么会发生这种情况,但我认为这可能与我对sessionStorage一无所知有关。

下面是代码:

Auth 服务

export class AuthService {
  private user: Observable<firebase.User>;
  private userDetails: firebase.User = null;
  public loggedIn = false;



  constructor(private _firebaseAuth: AngularFireAuth, private router: Router) {
    this.user = _firebaseAuth.authState;
    this.loggedIn = !!sessionStorage.getItem('user');

    this.user.subscribe(
        (user) => {
          if (user) {
            this.userDetails = user;

            console.log(this.userDetails);
          } else {
            this.userDetails = null;
          }
        }
      );
  }

  // Set current user in your session after a successful login
    setCurrentUser(email: string): void {
        sessionStorage.setItem('user', email);
        this.loggedIn = true;
    }

    // Get currently logged in user from session
    getCurrentUser(): string | any {
        return sessionStorage.getItem('user') || undefined;
    }

    isLoggedIn() {
    return this.loggedIn;
    }

  logUserIn(email, pass) {
    firebase.auth().signInWithEmailAndPassword(email, pass).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log("error" + error);
})
//var user = firebase.auth().currentUser;
//var email;
if (this.userDetails) {
email = this.userDetails.email;
console.log("hello im user" + " " + email);
//email = user.email;
this.setCurrentUser(email);
 this.loggedIn = true;
} else {
console.log("not working");
}

this.router.navigate(['']);
}

  regUser(email, pass) {
    firebase.auth().createUserWithEmailAndPassword(email, pass)
 .catch(function(error) {
   // Handle Errors here.
   var errorCode = error.code;
   var errorMessage = error.message;
   // ...
 });
//console.log(this.form.controls['email'].value);
    }

    logOut() {
      this.loggedIn = false;
      firebase.auth().signOut().then(function() {
        // Sign-out successful.
        console.log("signout successful");
    }).catch(function(error) {
        // An error happened.
        console.log("error happened");
      });
    }

  }

登录组件

导出登录组件类:

form: FormGroup;

constructor(fb: FormBuilder, private _loginService: LoginService, private auth: AuthService){

    this.form = fb.group({
        email:['',Validators.required ],
  password:['',Validators.compose([Validators.required,

PasswordValidator.cannotContainSpace])]无法包含空格。

}

login(){
      this.auth.logUserIn(this.form.value.email, this.form.value.password);

};

}

app.component.ts,因为我在app.component.html中有我的路由出口和链接。

export class AppComponent {

  title = 'angular-draganddrop';
  constructor(private auth: AuthService) { }
  LoggedIn() {
      return this.auth.isLoggedIn();
  }
  logout() {
    return this.auth.logOut();
  }
}

编辑编辑:

我在Chrome中检查了应用程序的会话存储,当我退出登录时,我的用户电子邮件确实还在那里。我必须手动删除它。然后,在第一次尝试登录时,它不起作用,并且会话存储中也没有用户电子邮件。第二次才会添加。在将sessionStorage功能添加到代码之前,登录系统运行良好,因此肯定与此有关。我不知道sessionStorage是如何工作的,因此正在寻求帮助解决这个问题。

2个回答

2

您需要使用会话(session),以便在页面刷新时检查它。

只需在您的服务AuthService中设置和使用一个名为loggedIn的属性即可:

public loggedIn = false;

constructor(private _firebaseAuth: AngularFireAuth, private router: Router) {
    this.loggedIn = !!sessionStorage.getItem('user');
}

// Set current user in your session after a successful login
setCurrentUser(email: String): void {
    sessionStorage.setItem('user', email);
    this.loggedIn = true;
}

// Get currently logged in user from session
getCurrentUser(): string | any {
    return sessionStorage.getItem('user') || undefined;
}

// Clear the session for current user & log the user out
logout() {
    sessionStorage.removeItem('user');
    this.loggedIn = false;
    // ... other code for logout
}

// The method to check whether user is logged in or not
isLoggedIn() {
    return this.loggedIn;
}

所以,您更新后的 logUserIn 方法应该是 -
logUserIn(email, pass) {
    firebase.auth().signInWithEmailAndPassword(email, pass).catch(function (error) {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        console.log("error" + error);
    })

    if (this.userDetails) {
        email = this.userDetails.email;
        console.log("hello im user" + " " + email);
        // setting user in session here --->
        this.setCurrentUser(email);
    } else {
        console.log("not working");
    }

    this.router.navigate(['']);
}

在退出时,只需按照上述示例调用 logout()

然后将其添加到您的HTML中,如下所示 -

<li><a routerLink="login" routerLinkActive="active" *ngIf="!auth.isLoggedIn()">Login</a></li>

谢谢。注销对我有效。登录有点奇怪,我需要登录两次才能正常工作。首先,在Chrome中,我会收到“不工作”的控制台消息,这来自我的auth服务中的logUserIn函数。控制台显示错误:src/app/services/auth.service.ts(17,3): error TS2393: Duplicate function implementation. src/app/services/auth.service.ts(28,18): error TS2339: Property 'userDetails' does not exist on type 'AuthService'. src/app/services/auth.service.ts(40,40): error TS2345: Argument of type 'String' isnot assignable to parameter of type 'string'. - Limpuls
我马上会更新我的问题并附上新代码。 - Limpuls
是的,那就是发生的事情。不管怎样,我仍然看到一些奇怪的行为。我更新了我的 OP,如果可以,请检查一下。谢谢。 - Limpuls
我看到你使用了 sessionStorage.setItem()。在注销后,我是否也需要清除它? - Limpuls
尝试在成功登录后(在.then()中)将数据分配给您的userDetails - Tushar Walzade
显示剩余2条评论

1

有一种更简单的方法来完成这个任务。请参阅官方 Github 文档:https://github.com/angular/angularfire/blob/master/docs/auth/getting-started.md

你只需要...

myPage.component.ts

import { AngularFireAuth } from '@angular/fire/auth';
//...
constructor(public afAuth: AngularFireAuth) { }

myPage.component.html

<div *ngIf="(afAuth.user | async)">User is logged IN</div>
<div *ngIf="!(afAuth.user | async)">User is logged OUT</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接