如何通过Flutter代码创建Firestore用户集合并配置对应安全规则
问题根因
你遇到的权限校验失败问题来自两个核心错误:
- 代码层面:使用Google登录返回的账号ID作为Firestore用户文档ID,和安全规则中校验的Firebase Auth生成的
uid不是同一个值,导致规则匹配永远失败 - 安全规则层面:缺少
request.auth != null的非空判断,未登录用户访问时会触发规则空指针异常,直接拒绝请求
修复方案
第一步:修改Firebase安全规则
优化后的规则如下,同时新增了创建文档时的字段合法性校验,避免非法写入:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /users/{uid}/{document=**} { // 读、写、更新权限仅开放给对应用户本人 allow read, write: if request.auth != null && request.auth.uid == uid; // 可选:新增用户文档时的字段校验,可根据业务需求调整 allow create: if request.auth != null && request.auth.uid == uid && request.resource.data.keys().hasAll(['id', 'userName', 'photoUrl', 'email', 'displayName', 'bio', 'timestamp']) && request.resource.data.id == uid; } } }
说明:你之前单独写的jobs子集合规则已经被上面的通配符规则覆盖,不需要重复声明,可直接删除
第二步:修改业务代码
统一使用Firebase Auth返回的uid作为用户文档ID,调整createUserInFirestore方法逻辑:
Future<void> createUserInFirestore() async { // 从Firebase Auth实例获取当前登录用户,兼容所有登录方式 final User? currentUser = FirebaseAuth.instance.currentUser; if (currentUser == null) return; final usersRef = FirebaseFirestore.instance.collection('users'); final DocumentSnapshot userDoc = await usersRef.doc(currentUser.uid).get(); if (!userDoc.exists) { final userName = await Navigator.push( context, MaterialPageRoute(builder: (context) => const CreateAccountPage()), ); // 写入用户数据时统一使用Firebase Auth的用户属性 await usersRef.doc(currentUser.uid).set({ 'id': currentUser.uid, 'userName': userName, 'photoUrl': currentUser.photoURL, 'email': currentUser.email, 'displayName': currentUser.displayName, 'bio': '', 'timestamp': documentIdFromCurrentDate(), }); } }
说明:你原代码中对final声明的doc变量重复赋值属于语法错误,上述代码已经修复该问题
验证逻辑
修改完成后可按以下流程验证:
- 先登录任意账号,触发创建用户文档逻辑
- 查看Firestore控制台是否生成了对应用户uid的文档
- 测试修改用户信息、查询jobs子集合等操作,确认权限校验正常
内容的提问来源于stack exchange,提问作者Carleton Y
相关产品推荐
相关产品推荐

