firebase - 阻止用户更改 Firestore 中特定文档字段的问题

标签 firebase google-cloud-firestore google-cloud-functions firebase-security

我在 Android 项目中使用 firebase,我在 Cloud Firestore 数据库中有一个用户集合,用户只能更新某些字段,但可以读取所有字段,我知道不可能保护文档的子集正在更新,安全规则只能应用于整个文档,所以我对此进行了搜索,找到的唯一解决方案是在用户文档中创建一个子集合,并在该子集合中创建一个新文档,最后将我想要保护的字段,然后我可以在安全规则部分应用此代码轻松保护此文档:

match /users/{userId}/securedData/{securedData} {
  allow write: if false;
  allow read: if true;
}

所以现在没有人可以写这些字段,但是任何人都可以读,而这正是我想要的,但是后来我发现我需要根据子集合里面的字段来查询用户,也就是所谓的集合目前不支持组查询,所以我最终得到了两种解决方案:

  1. 检索所有用户并在客户端过滤它们,但这会增加文档读取的数量,因为我正在查询所有用户集合文档+为每个用户读取额外的子集合文档以获得所需的字段过滤用户。
  2. 不要在用户文档中创建子集合并引发这些问题,只需将所有字段保留在顶级文档(用户文档)中,允许用户更新任何字段。

    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/

相关文章:

firebase - 如何使用测试模式而不是锁定模式重新创建 Firebase Firestore 数据库

java - 使用 Query for FirestoreRecyclerAdapter 时,我没有调用 get() 但需要设置 Query.get(Source.SERVER)

Android使用Retrofit发送HTTP POST触发云功能

database - 如何在3个步骤中处理多个页面以保存用户数据,其中每个步骤都是一个新界面,然后将它们保存在一起?

ios - 如何在 iOS 中使用 Firebase 修复此 Signal SIGABRT?

firebase - gcloud firestore 导入是否会在任何场景下触发云功能?

javascript - 如何在node.js中触发firebase http函数?

swift - 删除文档时 Firestore 事务中如何处理错误

ios - UIKit 上的奇怪崩溃

javascript - 将新用户添加到 firebase 中现有用户的联系人列表中