Angular 2 - Firebase在页面刷新时保持登录状态

时间:2017-05-21 15:07:03

标签: javascript angular firebase firebase-authentication angularfire

所以我真的很接近这个想法。基本上,我有登录工作,我有代码设置来监视onAuthStateChanged,但问题是,当我刷新页面时,即使用户当前已登录,它仍然会重定向到/login页面,因为我已设置的auth guard,检查用户是否已登录。

我有一个auth服务设置,可以进行所有身份验证检查。

在我的身份验证服务构造函数中,我有onAuthStateChanged代码设置的地方:

constructor(
    private auth: AngularFireAuth,
    private router:Router,
    private db:AngularFireDatabase,
  ) {

    firebase.auth().onAuthStateChanged(function(user) {
     if (user) {
       // What do I need to put here to ensure that the auth guard goes to the intended route?
     }
    });

  }

以下是我的身份验证员canActivate()方法:

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

      if(this.authService.getAuthenticated()) {
        return Observable.of(true);
      } else {
        this.router.navigate(['/login']);
      }
    }

这是getAuthenticated()方法:

getAuthenticated() {
    return firebase.auth().currentUser;
  }

更新

以下是用户实际登录时调用的方法。在实际组件中,这是登录方法:

login(data, isValid) {
    if(isValid) {

      this.authService.login(data.email, data.password)
          .then(
              (data) => {
                console.log('data', data);
                this.router.navigate(['/projects'])
              }, error => {
                this._utilities.createToasty({
                  msg: "The email/password combination is incorrect.",
                  type: "error"
                });
              }
          );
    }
  }

在auth服务中,这是登录方法:

login(email, password) {
    return firebase.auth().signInWithEmailAndPassword(email, password);
  }

所以现在,我并不完全确定我需要在哪里放置哪些代码来确保当我的用户刷新页面时,auth警卫会选择并实际允许用户转到该路线总是重定向到/login路线。

思想?

5 个答案:

答案 0 :(得分:5)

我真的不知道答案,因为我不使用firebase所以那些更多的指针

猜1 :用户处于中间状态

当canActivate方法执行时,后台运行身份验证的功能尚未运行。因此,当前用户尚未设置。我想firebase只是转到你的本地存储并检查令牌是否有效。如果它是它的功能,那么只需确保在canActivate之前发生这种情况。

然而,如果它是异步的,那么它可以在之前运行并使当前用户仍未定义。然后你必须确保canActivate在结算后运行。

实际上,更好的是:在你的can activate方法中使用observable:

代码:

 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.af.auth.map((auth) => {
        if (!auth) {
          this.router.navigateByUrl('login');
          return false;
        }
        return true;
    }).take(1);
  }

猜猜2 :您必须将内容存储在本地存储中。

这些身份验证服务通常需要在localstorage中存储令牌,然后使用此令牌在页面刷新时对用户进行身份验证。在我能读到的内容中,这是在firebase的后台完成的。您仍然可以检查本地存储/会话存储,以确保您在那里看到信息。

如果您在localStorage / sessionStorage中没有看到任何相关信息,那么您可能需要在登录时输入一些内容。

答案 1 :(得分:2)

我遇到了和你一样的问题,我用localStorage解决了这个问题:

login(email, password): Observable<AuthInfo> {
    return this.fromFirebaseAuthPromise(this.afAuth.auth.signInWithEmailAndPassword(email, password));
}

我刚刚添加localStorage.setItem("user", this.afAuth.auth.currentUser.uid); 登录响应和localStorage.removeItem("user");登出方法。

fromFirebaseAuthPromise(promise): Observable<any> {

const subject = new Subject<any>();

promise
  .then(res => {
      const authInfo = new AuthInfo(this.afAuth.auth.currentUser.uid);
      this.authInfo$.next(authInfo);
      subject.next(res);
      subject.complete();
      localStorage.setItem("user", this.afAuth.auth.currentUser.uid);
    },
    err => {
      this.authInfo$.error(err);
      subject.error(err);
      subject.complete();
    });

    return subject.asObservable();
}



logout() {
    this.afAuth.auth.signOut();
    localStorage.removeItem("user");
    this.authInfo$.next(AuthService.UNKNOWN_USER);
    this.router.navigate(['/login']);
}

并将canActivate()方法更改为以下内容:

canActivate() {
        //you can check token is exists or not here
        if (localStorage.getItem('user')) {
            console.log("user ist logged in ....", localStorage.getItem('user'));

            return true;
        } else {
            console.log("user is not logged in");

            this.router.navigate(['/login']);
            return false;
        }
    }

答案 2 :(得分:0)

firebase.auth().onAuthStateChanged(function (user) {
   console.log('onAuthStateChanged: ', user);
});

答案 3 :(得分:0)

让我尝试通过将用户数据保存在本地存储中来解决此问题。 当用户登录时,我的逻辑很简单,我们会将用户数据保存在本地存储中,这样即使重新加载页面后,我们也可以拥有用户状态。

userData: any;

constructor(
    public afAuth: AngularFireAuth
) {    
    this.afAuth.authState.subscribe(user => {
      if (user) {
        localStorage.setItem('user', JSON.stringify(this.userData));
        JSON.parse(localStorage.getItem('user'));
      } else {
        localStorage.setItem('user', null);
        JSON.parse(localStorage.getItem('user'));
      }
    })
  }

答案 4 :(得分:0)

在setTimeout内编写代码。因为 刷新页面后会发生此问题。

setTimeout(()=>{
console.log("currentUser", firebase.auth().currentUser);
},1000)