Firebase Firestore规则阻止已认证用户访问数据的问题排查
解决Firebase Firestore「Missing or insufficient permissions」权限错误
问题概述
React Native项目使用Firebase Firestore存储核心数据,调整安全规则后出现权限拒绝错误,无法满足App Store上架要求。具体需求:
ConnectWithAgent、GeneralConnect、SellMyHome、ShowingTour四个集合:允许所有人读写Favorites、Feed、Offers、Profiles、RecentViews五个集合:允许所有人写入,仅已登录认证用户可读(其中Favorites、Profiles、RecentViews需限制用户仅能访问自身userId匹配的文档)
已登录测试用户读取自身Favorites文档时触发以下错误:
ERROR [2023-06-26T17:59:41.457Z] @firebase/firestore: Firestore (9.21.0): Uncaught Error in snapshot listener: FirebaseError: [code=permission-denied]: Missing or insufficient permissions.
修正后的安全规则
根据需求,针对不同集合设置精准权限,同时对用户专属文档添加用户uid匹配验证,完整规则代码如下:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // 开放全权限的4个集合 match /ConnectWithAgent/{document=**} { allow read, write: if true; } match /GeneralConnect/{document=**} { allow read, write: if true; } match /SellMyHome/{document=**} { allow read, write: if true; } match /ShowingTour/{document=**} { allow read, write: if true; } // 用户专属文档集合:所有人可写,仅登录用户可读取自身文档 match /Favorites/{docId} { allow write: if true; allow read: if request.auth != null && resource.data.userId == request.auth.uid; } match /Profiles/{docId} { allow write: if true; allow read: if request.auth != null && resource.data.userId == request.auth.uid; } match /RecentViews/{docId} { allow write: if true; allow read: if request.auth != null && resource.data.userId == request.auth.uid; } // 开放给所有登录用户读取的集合:所有人可写,任意登录用户可读 match /Feed/{document=**} { allow write: if true; allow read: if request.auth != null; } match /Offers/{document=**} { allow write: if true; allow read: if request.auth != null; } } }
读取逻辑校验
确保读取代码正确获取用户uid并匹配文档字段,以下是Firebase v9的示例实现:
import { getAuth, onAuthStateChanged } from "firebase/auth"; import { collection, query, where, onSnapshot } from "firebase/firestore"; import { db } from "../path/to/firebaseConfig"; // 监听用户收藏数据(确保在用户登录后执行) const setupFavoritesListener = () => { const auth = getAuth(); onAuthStateChanged(auth, (user) => { if (!user) { console.log("用户未登录,无法读取收藏"); return; } const q = query(collection(db, "Favorites"), where("userId", "==", user.uid)); onSnapshot(q, (snapshot) => { const favorites = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); console.log("更新收藏数据", favorites); // 处理数据更新逻辑 }, (error) => { console.error("监听收藏失败", error); }); }); };
关键检查点
- 文档字段一致性:确认
Favorites等集合的文档中存在userId字段,且值与用户uid完全匹配(注意大小写) - 登录状态时机:通过
onAuthStateChanged监听用户登录状态,确保读取/监听操作在用户认证完成后执行 - 查询条件准确性:查询必须包含
userId == user.uid的条件,否则会触发权限规则拦截
调试方法
- 使用Firebase控制台的规则模拟器:模拟已登录用户读取自身文档的场景,验证规则是否生效
- 打印用户uid与文档userId:在读取前输出两者的值,确认是否一致
- 检查Auth状态:确保用户读取数据时处于已登录状态
内容的提问来源于stack exchange,提问作者ojandali
相关产品推荐
相关产品推荐

