【问题标题】:firestore security rules get value of dynamic key?firestore 安全规则获取动态密钥的值?
【发布时间】:2020-03-21 17:01:15
【问题描述】:

文档结构:

{
    [id 1] {
        field1: "value",
        field2: "value",
        field3: "value"
    }
    [id 2] {
        field1: "value",
        field2: "value",
        field3: "value"
    }
    [id 3] {
        field1: "value",
        field2: "value",
        field3: "value"
    }
}

地图ID参考文档,不能硬编码,但每个地图的字段名称(field1,field2...)都是相同的

有没有办法检查任何 1 个映射中只有 1 个字段被更改,如果满足这些条件则允许写入?

【问题讨论】:

  • 如果不知道字段名称,则无法从字段中获取值。你在这里的目标是什么?为什么需要这样做?
  • @DougStevenson 相关文档包含由随机 ID 引用的地图。我只需要允许更改 1 个地图中的 1 个子值。由于只能更改 1 个地图,因此 changedKeys() 仅包含 1 个项目,因此获取已更改地图的 id 的一种方法是获取从 changedKeys() 返回的集合中 id 的值,但我没有t 找到有关如何执行此操作的任何文档。那么有没有办法从Set 获取值,或者获取更改后的地图?
  • 很难从那段文本中想象你在做什么,但我认为随机字段名称在这里对你不利。不知道你在做什么是可能的。这并不是在 Firestore 中建模数据的好方法。
  • @DougStevenson 我把问题说清楚了,你能再看一下吗?

标签: google-cloud-firestore firebase-security


【解决方案1】:

为了将所有验证逻辑保留在 Firestore 中,您可以使用一个技巧,即为您的写入请求添加冗余。例如,您可以从客户端发送以下数据:

firestore.collection('A').doc('B').update({ 
  'your_id_here': { 
    field1: 'my new value',

    // keep old data, since we are updating a nested object
    field2: 'original value', 
    field3: 'original value'
  },
  
  // this is the redundancy component
  meta: { id: 'your_id_here' }
});

然后,您可以在 Firestore 规则中定义写入规则,如下所示:

function valid() {

  // grab ID from "redundant" part of the request
  let metaID = request.resource.data.meta.id;

  // grab changed keys in the root of the document
  let rootAftectedKeys = request.resource.data.diff(resource.data).affectedKeys(); 

  // validate root keys; need to include "meta", since it is now also part of the object
  let rootChangesGood = rootAffectedKeys.hasOnly([metaID, 'meta']);
  
  // grab the nested object in question             
  let nestedObjectChanges = request.resource.data[metaID].diff(resource.data[metaID]).affectedKeys();

  // check there was only one affected key
  let nestedObjectChangesGood = nestedObjectChanges.size() == 1;

  return rootChangesGood && nestedObjectChangesGood;
}
allow write: if valid();

如您所见,我正在使用metaID 变量来动态访问对象的键。

这种方法的优点是 (1) 所有验证逻辑都在 Firebase 中,(2) 它比执行云功能要快得多(因为您只是直接与 Firestore 通信)。

但是,这种方法的缺点是您将让这个meta 对象四处浮动,供所有人查看。最重要的是,我将添加更多验证以确保 meta 对象本身仅具有正确格式的所需数据。我强烈建议彻底测试所有可能的情况。

【讨论】:

    【解决方案2】:

    安全规则不够灵活,无法满足您的要求。这需要循环和赋值,这两者在语言中都不可用。我建议改为使用后端从客户端收集数据,然后检查它是否有效。

    【讨论】:

    • 谢谢,还有,有没有办法将集合转换为列表或从集合中获取一个 ttem,如果没有,是否可以在可预见的将来添加这些功能?
    • 如果您有新问题,请单独发布。
    • 在 Stack Overfow 上,通常会为有帮助的答案投票,并认为它们是正确的。
    猜你喜欢
    • 2019-01-15
    • 2018-06-15
    • 2020-04-29
    • 1970-01-01
    • 2020-07-07
    • 2020-01-14
    • 2018-10-19
    • 2019-07-05
    • 2020-05-10
    相关资源
    最近更新 更多