Android Firestore更新权限拒绝问题:仅允许修改name和photo字段
解决Firestore update()方法权限被拒的问题
嘿,这个问题我之前也碰到过,核心是你对Firestore安全规则里的request.resource和request.data的区别理解错了,导致update操作触发了权限限制。
问题出在哪?
你当前的规则里,update操作要求request.resource.data.size() == 2,还要求它的keys必须包含name和photo。但要注意:
- 当调用
set()方法时,request.resource.data就是你传入的完整文档数据,所以满足size为2的条件; - 但调用
update()时,request.resource.data是更新后的整个文档数据,它包含原来文档里的所有字段,再加上你这次更新的字段。如果你的用户文档原本就有其他字段(比如createdAt、email之类的),那size() == 2肯定不成立,直接触发PERMISSION_DENIED。
另外,hasAll(['name', 'photo'])也不是你想要的逻辑——它要求文档必须有这两个字段,但你真正想限制的是用户只能修改这两个字段,不能碰其他字段,对吧?
修正后的安全规则
下面是调整后的规则,完美适配你的需求:
service cloud.firestore { match /databases/{database}/documents { match /users/{user} { allow read: if request.auth.uid == user; allow update: if request.auth.uid == user && // 限制本次更新只能提交name和photo字段,不能加其他字段 request.data.keys().hasOnly(['name', 'photo']) && // 验证提交的字段类型正确(支持只更新其中一个的场景) (('name' in request.data) => request.data.name is string) && (('photo' in request.data) => request.data.photo is string); } } }
规则细节解释
request.data:这个才是你调用update()时传入的字段集合,而不是整个文档。用hasOnly确保用户不能提交这两个字段之外的任何数据,完全符合你“禁止输入其他数据”的要求。- 类型验证的条件写法:
(('name' in request.data) => request.data.name is string),意思是只有当本次更新包含name字段时,才需要验证它是字符串类型。这样用户可以选择只更新name,或者只更新photo,或者两个一起更,都能通过验证。 - 如果你非要强制用户每次更新必须同时改两个字段,那可以把
hasOnly换成hasAll,然后把类型验证改成request.data.name is string && request.data.photo is string,但个人不建议这么做,太死板了。
你的Java代码不用改
你写的Java更新逻辑是对的,传入的Map只有name和photo两个字段,完全符合修正后的规则,现在再调用update()应该就能正常成功了。
内容的提问来源于stack exchange,提问作者batyrf
相关产品推荐
相关产品推荐

