如何编写Firestore安全规则,仅允许对数组字段单次增删单个元素
Firestore 安全规则实现方案
以下规则可实现仅允许对meta集合下status文档的all数组字段执行单个元素的添加/移除操作,禁止其他所有修改行为:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // 匹配meta集合下的status文档 match /meta/status { // 允许读权限(满足拉取完整数组的前置需求) allow read: if true; // 写权限校验逻辑 allow write: if // 1. 仅允许修改all字段,禁止新增/修改/删除其他字段 request.resource.data.keys().hasOnly(["all"]) // 2. 校验all字段始终为字符串数组类型 && request.resource.data.all is list && request.resource.data.all.toSet().every(element => element is string) // 3. 校验仅为单个元素添加或移除操作 && ( // 情况1:移除单个元素:新数组比旧数组长度少1,且仅移除了1个元素无其他修改 (request.resource.data.all.size() == resource.data.all.size() - 1 && request.resource.data.all.toSet().difference(resource.data.all.toSet()).size() == 0 && resource.data.all.toSet().difference(request.resource.data.all.toSet()).size() == 1) // 情况2:添加单个元素:新数组比旧数组长度多1,且仅新增了1个元素无其他修改 || (request.resource.data.all.size() == resource.data.all.size() + 1 && resource.data.all.toSet().difference(request.resource.data.all.toSet()).size() == 0 && request.resource.data.all.toSet().difference(resource.data.all.toSet()).size() == 1) ); } } }
补充说明
- 如果需要限制访问身份,可以在
allow read和allow write的判断条件中新增登录校验(如request.auth != null),按需调整即可。 - 原有客户端的全量覆盖写逻辑可以正常通过规则校验,但高并发场景下建议改用Firestore原子数组操作
arrayRemove()和arrayUnion(),可以避免并发修改导致的数组内容覆盖问题,修改后客户端逻辑如下:// 移除单个元素的写法 metaRef.doc("status").update({"all": FieldValue.arrayRemove([ales])}); // 添加单个元素的写法 metaRef.doc("status").update({"all": FieldValue.arrayUnion([ales.toString()])});
内容的提问来源于stack exchange,提问作者Eight Rice
相关产品推荐
相关产品推荐

