firebase 火灾规则:resource.data.keys()不包含读取中的所有字段

euoag5mw  于 2023-01-14  发布在  其他
关注(0)|答案(2)|浏览(81)

设置

我在Firebase Firestore中有一个集合,其中包含以下字段:

(["active" , "created" , "description" , "displayName" , "expires" , "image" , "type" , "uid" , "userName"])

其中"expires"是可选的。
写入规则确保每个对象都遵循该格式并成功测试。
问题
当尝试从集合中读取时,我有一个规则,声明如下:

let seeUnexpired = !("expires" in resource.data.keys()) ||
resource.data.expires > request.time ||
request.auth.uid == resource.data.uid;

这禁止用户以外的作者读取过期的条目。这条规则并不禁止读取,但是。我正在测试使用本地模拟器与精心策划的数据,并确信过期字段存在,并已过时的这个测试。

详情

在尝试调试时,我发现导致规则失败的条件是!("expires" in resource.data.keys())
使用debug(resource.data.keys())运行测试,将此对象输出到firestore-debug.log

list_value {
  values {
    string_value: "active"
  }
}

其中"active"仅在请求中使用此查询条件时显示:...collection('collection_name').where('active', '==', true).get().
这表明resource.data.keys()只包含读取请求中where子句引用的资源字段,这意味着请求可以绕过"字段必须不存在"规则,只需在查询中不包含它。
调试:

Mar 31, 2021 12:34:48 PM io.gapi.emulators.netty.HttpVersionRoutingHandler channelRead
INFO: Detected non-HTTP/2 connection.
list_value {
  values {
    string_value: "active"
  }
}

测试

试验:

await firestoreAdmin.collection(COLLECTIONS.items).doc(mockItem.id).update({active: true, expires: new Date('01 Jan 2000 00:00:00 GMT')});
const query = firestore.collection(COLLECTIONS.items).where('active', '==', true); //unAuthed firestore instance
await assertFails(query.get());

规则:

function readItemRules() {
  let seeActive = resource.data.active == true || request.auth.uid == resource.data.uid;
  let seeUnexpired = !("expires" in resource.data.keys()) ||
  resource.data.expires > request.time ||
  request.auth.uid == resource.data.uid; TODO figure out expiration rules
  return seeActive && seeUnexpired;
}

数据:

问题

我对这个问题的理解是否准确,或者我是否遗漏了一个细节或语法异常?这种行为是故意的吗?如果是,我应该如何修改我的规则/数据来实施这种安全性?

r7xajy2e

r7xajy2e1#

我发现对于读规则,firestore似乎只从查询中提到的文档中加载字段,这对于要求字段存在或匹配某些内容的规则很有意义。因为如果不将其包含在查询中,它们肯定会失败(因为它们将针对未定义的内容进行测试)。它在这里不起作用,因为如果您从查询中省略它,则会“无论如何,我都将通过不存在规则,因为Firestore在执行检查时会从整个资源中忽略该字段。
我的解决方案只是添加另一个布尔字段“hasExpiration”,指示“expires”字段是否存在。我对这个解决方案有点不满意,因为它增加了复杂性,并且福尔斯客户机/写入规则来确保这些字段之间的奇偶性。
https://firebase.google.com/docs/firestore/security/rules-query#rules_are_not_filters
https://firebase.google.com/docs/firestore/security/rules-structure#granular_operations

myzjeezk

myzjeezk2#

https://firebase.blog/posts/2021/01/code-review-security-rules
这一页上的例子很棒,尤其是最后一个:

allow update: if
  // Immutable fields are unchanged
  request.resource.data.diff(request.resource.data).unchangedKeys().hasAll([
    "authorUID",
    "publishedAt",
    "url"
  ]) &&
  // Required fields are present
  request.resource.data.keys().hasAll([
    "content",
    "title",
    "visible"
  ]);

它显示了keys()的列表和一种智能计算unchangedKeys()的方法。

相关问题