我在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 });
}
});
第二种解决方案安全吗?哪个是最好的解决方案?或任何其他解决方案?
答案 0 :(得分:2)
您的方法肯定是可能的,并且是对Cloud Functions的有趣使用。但是,从用户进行写操作到Cloud Function检测到并还原更改之间会有一段时间。
我可能会在安全规则中遇到这种情况。虽然您不能拒绝用户在安全规则中写入字段,但您可以 确保用户只能向当前具有相同字段的字段写入相同的值。这实际上也使他们无法更改字段的值。您可以通过以下方式做到这一点:
allow write: if request.resource.data.securedField == resource.data.securedField;
此规则确保更新文档(request.resource.data.securedField
)中的字段与当前文档(resource.data.securedField
)中的字段具有相同的值。