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

Cloud Firestore规则问题:为何写入时提示权限被拒绝?

问题:Cloud Firestore写入操作触发权限异常

Firestore数据结构

Cloud Firestore
 |-users
     |-user1
         |-user1data
     |-user2
         |-user2data

当前安全规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{uid} {
      allow read, write: if
          request.auth.uid == uid;
    }
  }
}

问题描述

尝试写入数据时,触发FirebaseException异常,提示「调用者无权执行指定操作」。需求是允许用户对自己的数据库集合进行读写,同时保证用户数据相互隔离,在Realtime Database中能轻松实现,但在Cloud Firestore中遇到困难。

补充代码

登录状态判断(main.dart)

class Decider extends ConsumerWidget {
  const Decider({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final user = ref.watch(userProvider).value;
    if (user != null) {return const HomePage();
    } else {return const LoginPage();}}

final userProvider = StreamProvider<User?>((ref) => FirebaseAuth.instance.authStateChanges());

登录逻辑(可正常工作)

onPressed: () async {
        try {
          await ref.read(authRepositoryProvider).signInWithEmailAndPassword(
                email: emailController.text.trim(),
                password: passwordController.text.trim(),
              );
          if (context.mounted) {
            Navigator.pushReplacement(
                context,
                CupertinoPageRoute<void>(
                    builder: (BuildContext context) => const HomePage()));
          }
        } on FirebaseAuthException...

触发错误的调用代码

...onPressed: () {
                ref
                    .read(firestoreRepositoryProvider)
                    .addPayee(name: nameController.text.trim());
                if (context.mounted) {
                  Navigator.pop(context);
                }
              },...

写入方法实现

Future<void> addPayee({required String name}) =>
      _firestore.collection('users/$uid/payees').add({
        'name': name,
      });

问题排查与解决方案

核心原因:安全规则未覆盖子集合

当前规则仅匹配了/users/{uid}这个文档节点,但你的写入操作是在users/$uid/payees子集合下添加文档。Firestore安全规则默认不会自动递归应用到子集合,因此当前规则无法授权子集合的读写操作。

修正后的安全规则

提供两种可行的修正方案:

方案1:显式匹配子集合

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 授权用户文档本身的读写
    match /users/{uid} {
      allow read, write: if request.auth.uid == uid;
      // 授权该用户下所有子集合的读写
      match /{subcollection}/{document} {
        allow read, write: if request.auth.uid == uid;
      }
    }
  }
}

方案2:递归匹配所有层级(更简洁)

使用**通配符匹配users/{uid}下的所有文档和子集合:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{uid}/** {
      allow read, write: if request.auth.uid == uid;
    }
  }
}

该规则完全满足“用户仅能读写自己的数据、数据相互隔离”的需求。

额外验证点

  • 确认addPayee方法中的uid是当前登录用户的有效UID,避免出现UID为空或错误的情况
  • 可在写入前增加登录状态校验,确保用户处于已登录状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:05:23