我在我的Android项目中使用firebase,我在Cloud Firestore数据库中有一个用户集合,用户只能更新一些字段,但可以读取所有字段,我知道不可能保护文档的一个子集不被更新,安全规则只能应用于整个文档,所以我搜索了一下,我找到的唯一解决方案是在用户文档中创建一个子集合,并在这个子集合中创建一个新文档,最后将我想要保护的字段放在那里,然后我可以在安全规则部分应用以下代码来轻松地保护这个文档:
match /users/{userId}/securedData/{securedData} {
allow write: if false;
allow read: if true;
}
所以现在没有人可以写这些字段,但任何人都可以阅读,这正是我想要的,但后来我发现我需要根据子集合中的字段来查询用户,这就是目前不支持的集合组查询,所以我最终提出了两个解决方案:
- 检索所有用户并在客户端对其进行筛选,但这将增加文档读取次数,因为我正在查询所有用户的集合文档+为每个用户额外读取的子集合文档,以获得筛选用户所需的字段
与其在用户文档中创建子集合并引发这些问题,不如将所有字段保留在顶级文档(用户文档(中,允许用户更新任何字段。
match /users/{userId} { allow update, read: if true; allow create, remove: if false; }
但是制作一个(onUpdate(云函数来监听用户文档的更新和检测用户不允许修改的字段中的更改,因此如果用户试图更改这些字段,我可以检测到这一点,并将修改后的字段返回到以前的值,如下所示:
export const updateUser = functions.firestore .document('users/{userId}') .onUpdate((change, context) => { const previousValue = change.before.data().securedField; const newValue = change.after.data().securedField; if (previousValue !== newValue) { return db.collection('users') .doc(context.params.userId) .update({ securedField: previousValue }); } });
第二个解决方案是否安全?哪一个是最好的解决方案?或任何其他解决方案?
您的方法无疑是一种可能性,也是云函数的一种有趣使用。但是,从用户的写入操作到云功能检测到并恢复更改之间会有延迟。
我可能会在安全规则中发现这种情况。虽然您不能拒绝用户在安全规则中写入字段,但可以确保他们只能向当前具有的字段写入相同的值。这实际上也使他们无法更改字段的值。您可以通过:
allow write: if request.resource.data.securedField == resource.data.securedField;
此规则确保更新文档(request.resource.data.securedField
(中的字段与当前文档(resource.data.securedField
(中的该字段具有相同的值。