Firestore规则无法读取现有数据,求排查权限拒绝原因
Firestore权限拒绝问题解决
问题背景
Firestore数据库中文档包含playerCount = 1(整数类型)和isStarted = true(布尔类型)字段,使用以下规则时,Android端执行指定查询始终返回Permission Denied,无法读取resource.data.isStarted和resource.data.playerCount。
当前Firestore规则
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /props/{propId} { allow list,write,create: if false; allow read: if isLoggedIn() && propId=="7Ia********iqDO"; } match /rooms/{roomId=**} { allow create: if isLoggedIn(); allow read, list: if roomData("KjUXL49I1XVlXDGZ8jqL").playerCount==1 || resource.data.playerCount == 1 || oldData().isStarted || authData().uid in oldData().accessIds; allow write: if authData().uid in oldData().accessIds; } } function isLoggedIn() { return authData() != null;} function authData() { return request.auth } function oldData() { return resource.data } function newData() { return request.resource.data } function roomData(roomPath) { return get(/databases/$(database)/documents/rooms/$(roomPath)).data } }
Android查询代码
FirebaseFirestore.getInstance().collection("rooms").whereEqualTo("roomId", "023340").limit(1).get(Source.SERVER).addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { if(task.isSuccessful()){ ArrayList a = (ArrayList)task.getResult().getDocuments().get(0).getData().get("accessIds"); Log.d("sdccddsdcswc", String.valueOf(a.size())); } else { toast("Failed to read Room"); } } });
问题原因
自定义函数混淆概念
你定义的oldData()函数指向resource.data,但读取规则中resource.data本身就代表数据库中现有文档的数据,额外封装不仅冗余,还容易引发逻辑误解。读取操作中不存在request.resource,直接使用resource.data即可访问文档字段。规则与查询逻辑不匹配
Firestore规则采用集合级过滤机制,要求规则能验证所有符合查询条件的文档都满足权限要求。你的查询是按roomId=023340过滤,但规则中未关联该查询条件;同时硬编码的roomData("KjUXL49I1XVlXDGZ8jqL")仅验证特定文档的playerCount,与目标查询文档无关。读取条件逻辑缺陷
规则中的oldData().isStarted实际等同于resource.data.isStarted,但规则引擎无法在集合层面验证所有符合roomId=023340的文档都满足playerCount=1、isStarted=true或用户在accessIds中,因此直接拒绝整个查询。
修正方案
调整后的Firestore规则
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /props/{propId} { allow list,write,create: if false; allow read: if request.auth != null && propId=="7Ia********iqDO"; } match /rooms/{roomId} { allow create: if request.auth != null; // 读取规则:已登录用户,且满足任一权限条件 allow read, list: if request.auth != null && ( resource.data.playerCount == 1 || resource.data.isStarted == true || request.auth.uid in resource.data.accessIds ); allow write: if request.auth.uid in resource.data.accessIds; } } }
关键修改点
- 移除冗余自定义函数,直接使用Firestore原生变量
request.auth和resource.data,避免概念混淆 - 简化读取规则逻辑,明确验证当前文档的字段状态或用户权限
- 去掉
rooms匹配规则中的=**,仅匹配rooms集合下的一级文档(若无需子集合权限控制)
额外验证步骤
- 确认查询目标文档
roomId=023340确实存在playerCount=1、isStarted=true,或当前登录用户的UID在accessIds列表中 - 测试时可临时放宽规则(如
allow read: if request.auth != null;)验证是否为规则问题,之后再恢复严格权限
内容的提问来源于stack exchange,提问作者Nikhil Reddy
相关产品推荐
相关产品推荐

