firebase - 允许更新时如何保护 Firestore 文档中的字段?
问题描述
使用 Firebase Firestore,我将聊天室详细信息存储在包含以下数据的文档中:
roomName
roomAvatar
createDate
isDeleted
我的应用程序和我的规则要求在“创建”文档时设置这些字段。但是,我也希望授权用户也可以“更新”文档。
我已经进行了检查,只允许某些用户能够更新文档并验证他们不允许修改像“createDate”这样的字段。但是,我似乎无法创建一个规则来强制授权用户不删除“createDate”字段,无论是通过传递 FiledValue.delete() 还是使用 ref.set(objectMissingCreateDate)。
最后,如果客户端只尝试更新一个或两个字段,我认为不应该要求客户端在更新时传递所有数据字段。
我有一个“更新”规则如下:
allow update: if isAuthenticated() && isMemberOfRoom() &&
(
(!("roomName" in request.resource.data) ||
request.resource.data.roomName == resource.data.roomName ||
hasRoomPermission("UpdateRoom")) &&
(!("roomAvatar" in request.resource.data) ||
request.resource.data.roomAvatar == resource.data.roomAvatar ||
hasRoomPermission("UpdateRoom")) &&
(!("createDate" in request.resource.data) ||
request.resource.data.createDate == resource.data.createDate) &&
(!("isDeleted" in request.resource.data) ||
request.resource.data.isDeleted == resource.data.isDeleted ||
hasRoomPermission("DeleteRoom"))
);
主要问题是保护数据不被授权用户传入 FieldValue.delete() 或使用 [Android] docRef.set() 而缺少必需的值。
我什至会接受为非管理员客户端关闭 FieldValue.delete() 和破坏性“设置”操作的功能。
解决方案
在 Doug 和 Puff 的评论的帮助下,我意识到我做错了什么。
首先,我不知道只传递几个字段的更新(或带有合并选项的集合)会导致其余字段request.resource
从数据库的resource
.
其次,一个集合(没有合并)或传入一个将是丢失现有文档字段FieldValue.delete()
的唯一方法。request.resource
有了这些新知识,我将之前的规则更新为以下内容:
allow update: if isAuthenticated() && isMemberOfRoom() &&
(
("roomName" in request.resource.data &&
(request.resource.data.roomName == resource.data.roomName ||
hasRoomPermission("UpdateRoom"))) &&
("roomAvatar" in request.resource.data &&
(request.resource.data.roomAvatar == resource.data.roomAvatar ||
hasRoomPermission("UpdateRoom"))) &&
("createDate" in request.resource.data &&
request.resource.data.createDate == resource.data.createDate) &&
("isDeleted" in request.resource.data &&
(request.resource.data.isDeleted == resource.data.isDeleted ||
hasRoomPermission("DeleteRoom")))
);
这些新规则现在createDate
为客户端锁定,同时允许编辑roomName
、roomAvatar
和isDeleted
通过权限测试的客户端。它也不允许在对象缺少这些字段之一的地方更新FieldValue.delete()
或调用这些字段中的任何一个。docRef.set(object)
推荐阅读
- android - 你可以直接在android应用程序中链接静态库吗?
- php - mPDF - 用于生成 PDF 文件的 html 代码块内的 PHP 脚本
- docker - 如何在 Docker 中为 Java 11 设置内存限制?
- c# - QueueTrigger 函数能否作为控制器进行响应
- python - 从脚本 Python/R 打开 plotly html 文件
- python - 指定代码覆盖数据文件的位置
- c++ - 父类的后代即使在声明为朋友后也无法访问其宿主类的私有成员数据字段
- c - 如何从 C git repo 生成 32 位 dll
- python - numpy.resize() 和 cv2.resize() 有什么区别?
- pandas - pandas 将不均匀的每小时数据重新采样到 1D 或 24h 箱中