如何使用 Capacitor 的 Storage Plugin 将用户数据存储到本地存储?

How to store user data in local storage using Capacitor’s Storage Plugin?

我正在尝试将 Firebase 身份验证添加到我的 Angular 应用程序。

这是我 AuthService 中的 signUp() 方法:

signUp(email: string, password: string, name: string) {
    const userCredential = from(
      firebase.auth().createUserWithEmailAndPassword(email, password)
        .then(
          (data) => {

            let newUser: firebase.User = data.user;

            newUser.updateProfile({
              displayName: name,
              photoURL: ''
            }).then(() => {
              firebase.firestore().collection('users').add({
                userId: firebase.auth().currentUser.uid,
                userName: firebase.auth().currentUser.displayName,
                created: firebase.firestore.FieldValue.serverTimestamp()
              });
            });
            Plugins.Storage.set({
              key: 'userCredential',
              value: newUser.uid
            });
          }
        )
    );
    return userCredential;
  }

通过这种方法,我可以使用 Capacitor 的 Storage 插件将 newUser.uid 存储在本地存储器中。

但我希望能够存储与下面存储的信息相同的信息(即 localIdemailidTokenexpirationTime:

 login(email: string, password: string) {
    return this.http.post<AuthResponseData>(
      `firebaseUrl/v1/accounts:signInWithPassword?key=${
      environment.firebaseAPIKey
      }`,
      { email: email, password: password, returnSecureToken: true }
    ).pipe(tap(this.setUserData.bind(this)));
  }

private setUserData(userData: AuthResponseData) {
    const expirationTime = new Date(
      new Date().getTime() + (+userData.expiresIn * 1000)
    );
    this._user.next(
      new User(
        userData.localId,
        userData.email,
        userData.idToken,
        expirationTime
      )
    );
    this.storeAuthData(userData.localId, userData.idToken, expirationTime.toISOString(), userData.email);
  }

  private storeAuthData(userId: string, token: string, tokenExpirationDate: string, email: string) {
    const data = JSON.stringify({
      userId: userId,
      token: token,
      tokenExpirationDate: tokenExpirationDate,
      email: email
    });
    Plugins.Storage.set({ key: 'authData', value: data });
  }

谁能告诉我如何在我的 signUp() 方法中获得这 4 个值?

根据 docs.signInWithEmailAndPassword returns a Promise<UserCredential>。这意味着您可以在应用程序状态中保留某种结果以确定当前用户是谁。

使用localStorage的简单示例:

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

调用login(..., ...)后,可将成功结果存入localStorage:

localStorage.createItem('auth', userCredential)

然后,在你的守卫中,你可以检查一下 localStorage:

中的内容
canLoad(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    const userCredential = localStorage.getItem('auth');
    // TODO: some validation step
    return !!userCredential; // or the result of your validation
  }

另一种方法是利用您的 onAuthStateChanged 回调:

firebase.auth().onAuthStateChanged(user => {
      if (user) {
        localStorage.setItem('auth', user);
        console.log('Logged In User:', user);
      } else {
        console.log('Not Logged In');
        this.router.navigateByUrl('login');
      }
});

然后很明显,当用户注销或发生应该使会话无效的事情时,您想从 localStorage:

中删除该项目

localStorage.removeItem('auth');

我建议采用 NgRx 之类的方法或一些状态管理来帮助您管理用户状态,但如果您愿意,也可以使用本地存储。就安全性而言,我假设您在每个 API 请求中传递某种 API 密钥或 JWT 以验证用户。

根据您希望守卫的性能如何,您还可以查看 firebase API 看看它是否有任何类型的验证检查,您可以在本地存储中调用。

例如,在 UserCredential 中,您有某种身份验证令牌。然后,您可以使用所述身份验证令牌调用 firebase,如果该令牌是否有效,则该令牌应该 return a true/false。您可以将其作为一种更 "direct" 的方式来验证用户访问权限。但是,这也会降低守卫的性能,因为每次使用守卫时它都必须进行 API 调用。本地存储不会出现这个问题。

授权服务Login():

login(email: string, password: string) {
    const userCredential = from(firebase.auth().signInWithEmailAndPassword(email, password).then(loggedInUser => {
      Plugins.Storage.set({
        key: 'userCredential',
        value: loggedInUser.user.displayName
      });
    }));
    return userCredential;
  }

Auth Guard:

userCredential;

canLoad(
    route: Route,
    segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean {
    return Plugins.Storage.get({ key: 'userCredential' }).then(userCredential => {
      this.userCredential = userCredential;
      return this.autoLogin();
    });
  }

  autoLogin() {
    if (!this.userCredential || this.userCredential.value === null) {
      this.router.navigateByUrl('login');
      return false;
    } else {
      return true;
    }
  }