我在 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
)。
关于firebase - 阻止用户更改 Firestore 中特定文档字段的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53301895/