Firebase Cloud Firestore安全规则问题:用户仅能读取同公司预约数据
解决Firestore安全规则导致的集合查询权限错误
问题根源
你当前的安全规则仅针对单个文档读取/修改做了权限验证,但Firestore处理集合查询时,不会逐个检查返回的文档(出于性能考量),而是要求规则能验证你的查询约束与权限条件完全匹配,确保返回的所有文档必然符合权限要求。原规则仅通过resource.data.company_id验证单个文档,无法证明查询本身只会返回符合条件的记录,因此触发权限错误。
解决方案
1. 优化安全规则(支持单文档+集合查询)
修改规则,同时验证两个核心条件:
- 单个文档的
company_id与当前用户的company_id匹配 - 集合查询必须包含
company_id == 当前用户company_id的约束条件
match /appointments/{appointment} { allow write; allow read, update, delete: let userCompany = get(/databases/$(database)/documents/users/$(request.auth.uid)).data.company_id; return resource.data.company_id == userCompany && (request.query == null || request.query.where.any(condition => condition.field == 'company_id' && condition.op == '==' && condition.value == userCompany)); }
2. (可选)优化性能:使用自定义Claims
频繁调用get()读取用户文档会增加规则的性能开销,建议将用户的company_id存入Firebase Auth自定义Claims,避免重复读取用户文档:
步骤1:在后端设置自定义Claims(比如Cloud Functions)
// 示例:用户创建或更新时设置Claims const admin = require('firebase-admin'); admin.initializeApp(); async function setUserCompanyClaim(uid, companyId) { await admin.auth().setCustomUserClaims(uid, { company_id: companyId }); }
步骤2:修改安全规则
match /appointments/{appointment} { allow write; allow read, update, delete: let userCompany = request.auth.token.company_id; return resource.data.company_id == userCompany && (request.query == null || request.query.where.any(condition => condition.field == 'company_id' && condition.op == '==' && condition.value == userCompany)); }
3. 确保前端查询参数正确
确认前端代码中使用的company_id是当前登录用户文档中的值,而非任意传入的参数:
// 先获取当前用户的company_id const userDocRef = doc(db, 'users', auth.currentUser.uid); const userDoc = await getDoc(userDocRef); const company_id = userDoc.data().company_id; // 再执行查询 const q = query(collection(db, 'appointments'), where("company_id", "==", company_id), orderBy("createdAt"));
内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

