如何将凭据存储到本地存储以允许 Firebase 身份验证登录

ine*_*now 4 javascript firebase-authentication angularfire2 angular google-cloud-firestore

我正在从事 Angular 10 项目,我还使用 firebase 托管和云 firestore (用于数据库)。我也在我的项目中使用 AngularFire。

我的项目已经能够从我的 firestore 集合中获取文档并显示它们(也可以编辑、删除和创建它们)。我还设置了身份验证,使用 AngularFireAuth 进行登录和注销。我还设置了路由防护,仅允许用户在登录后访问信息。

我发现 Firestore 也有规则,您应该设置它们以保护您的收藏。目前,我基本上没有规则(测试模式),但我想添加基本的“只有用户可以访问任何内容”规则,但遇到了问题。

我认为这就是问题所在,目前,登录我的应用程序后会将用户存储在本地存储中。我认为我需要以不同的方式存储它,以便我从之前给出的凭据重新登录,而不是仅仅检查是否有本地存储。仅ERROR FirebaseError: Missing or insufficient permissions当我的警卫检查本地存储以确保登录时,我才会收到错误,如果我先登录,则不会收到错误。

那么,我应该如何保存用户数据,以便不必在每次刷新时登录,但可以验证 Firebase 的身份验证?我知道我可以将电子邮件/密码存储到本地存储并检查以重新登录,但这对我来说似乎不安全。

我认为以上是问题所在,但不能100%确定。

这是我的 Firestore 规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
  allow read, write: if request.auth != null
    match /{document=**} {
      allow read, write: if request.auth != null //should only allow users?
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这是我的身份验证服务(我在其中处理登录/注销并检查本地存储是否有用户)。

export class AuthService {
  constructor(private aFAuth: AngularFireAuth, public router: Router) {
    //I honestly don't know if I need this
    this.aFAuth.authState.subscribe((user) => {
      if (user) {
        localStorage.setItem('my-test-app-currentUser', JSON.stringify(user));
      } else {
        localStorage.setItem('my-test-app-currentUser', null);
      }
    });
  }

  async signIn(email: string, password: string) {
    this.aFAuth
      .signInWithEmailAndPassword(email, password).then((result) => {
        localStorage.setItem('my-test-app-currentUser', JSON.stringify(result.user));
        this.router.navigate(['']);
      }).catch((error) => {
        window.alert(error.message);
      });
  }

//this is the func that needs to change, if I have storage, I need to be able to sign-in with it again
  isSignedIn(): boolean {
    if (!localStorage.getItem('my-test-app-currentUser')) {
      return false;
    }
    return true;
  }

  signOut() {
    return this.aFAuth.signOut().then(() => {
      localStorage.removeItem('my-test-app-currentUser');
      window.alert('You have been signed-out');
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

这是我的守卫:

canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    // return true;
    if (this.auth.isSignedIn()) {
      return true;
    } else {
      this.router.navigate(["sign-in"]);
      return false;
    }
  }
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激。

Fra*_*len 6

Firebase already stores the user credentials in local storage, and automatically restores them when you reload the page.

Restoring them does require a check against the server though, so it happens asynchronously. For that reason, any code that depends on the user's authentication state should be inside the this.aFAuth.authState.subscribe handler, so that it runs whenever the authentication state changes.

So instead of handling the navigation when the signInWithEmailAndPassword call completes, which happens only when you actively sign the user in, the navigation should be in the auth listener, which runs both on active sign in and on a restore.

So something like:

export class AuthService {
  constructor(private aFAuth: AngularFireAuth, public router: Router) {
    //I honestly don't know if I need this
    this.aFAuth.authState.subscribe((user) => {
      if (user) {
        localStorage.setItem('my-test-app-currentUser', JSON.stringify(user));
        this.router.navigate(['']);
      } else {
        localStorage.setItem('my-test-app-currentUser', null);
      }
    });
  }

  async signIn(email: string, password: string) {
    this.aFAuth
      .signInWithEmailAndPassword(email, password).then((result) => {
        window.alert(error.message);
      });
  }
  ...
Run Code Online (Sandbox Code Playgroud)

In your canActivate you'll probably want to use the AngularFireAuthGuard. which ensures that unauthenticated users are not permitted to navigate to protected routes. I think this might replace your entire need for local storage.

另请参阅有关 Firebase 身份验证入门使用 AngularFire Guards 路由用户的AngularFire 文档。