You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular+Firebase如何通过IsApproved字段控制用户登录权限

实现方案

问题根源说明

你遇到的两个错误核心原因一致:Firebase Auth返回的内置User对象与你存储在Firestore中自定义User集合的文档是完全独立的两个数据结构:

  1. 登录时data.user是Firebase认证体系内置对象,仅包含uid、邮箱等认证基础字段,不存在你自定义的IsApproved字段,直接访问自然会抛出类型错误
  2. 安全规则中request.auth.uid是字符串类型的用户ID,不包含任何自定义字段,直接取IsApproved属性必然报错

1. 登录逻辑修复

登录成功后先查询Firestore中对应当前用户uid的文档,获取你自定义的用户数据再做判断,修改后的SignIn代码如下:

import { User } from '你的User接口文件路径'; // 先导入你自定义的User接口

async SignIn(email,password)
{
  const loading =await this.LoadingCtrl.create({
    message:'Authenticating..',
    spinner:"crescent",
    showBackdrop:true
  });
  loading.present();
  this.afauth.setPersistence(firebase.default.auth.Auth.Persistence.LOCAL)
  .then(()=>{
    this.afauth.signInWithEmailAndPassword(email,password)
    .then(async (data)=>{ // 这里加async支持内部await
      if(!data.user){
        loading.dismiss();
        this.toast('Please check your credentials','warning');
        this.afauth.signOut();
      }else{
        // 查询Firestore中当前用户的自定义数据
        const userDocRef = this.afs.collection('user').doc<User>(data.user.uid);
        const userDoc = await userDocRef.get().toPromise();
        const userData = userDoc.data();
        
        loading.dismiss();
        if(userData?.IsApproved === true){
          this.router.navigate(['/menu']);
        }else{
          this.afauth.signOut(); // 未审核用户直接清除登录状态,避免越权访问
          this.toast('账号尚未通过审核,请联系管理员','warning');
          this.router.navigate(['/accessdenied']);
        }
      }
    })
    .catch(error=>{
      loading.dismiss();
      this.toast(error.message,'danger');
    })
  })
  .catch(error=>{
    loading.dismiss();
    this.toast(error.message,'danger');
  });
}

如果你的RxJS版本高于7,toPromise()已废弃,可以替换为firstValueFrom():

import { firstValueFrom } from 'rxjs';
// 替换查询语句为
const userDoc = await firstValueFrom(userDocRef.get());

2. 路由守卫补充(推荐)

仅在登录环节做校验无法阻止用户直接通过URL访问受保护页面,建议新增Angular路由守卫,所有受保护路由的canActivate配置为守卫类,守卫内逻辑和登录校验一致:先判断是否登录,再查询IsApproved字段,不符合要求直接跳转accessdenied页。


3. Firestore安全规则修复

安全规则需要主动查询对应uid的用户文档校验IsApproved字段,正确规则如下:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 放行注册时的用户文档写入权限
    match /user/{userId} {
      allow create: if request.auth != null && request.auth.uid == userId;
      allow read, update, delete: if request.auth != null && request.auth.uid == userId;
    }
    // 其余所有资源仅允许已审核用户访问
    match /{document=**} {
      allow read, write: if request.auth != null 
        && exists(/databases/$(database)/documents/user/$(request.auth.uid))
        && get(/databases/$(database)/documents/user/$(request.auth.uid)).data.IsApproved == true;
    }
  }
}

注意规则优先级,自定义集合的独立规则要放在通配符规则之前,避免被通配符规则覆盖。


内容的提问来源于stack exchange,提问作者Notation

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 02:57:02