Firebase 安全规则在 get() 和 getAfter() 之间的区别



在文档中,它说:

使用 get() 和 exists() 函数,您的安全规则可以 根据数据库中的其他文档评估传入请求。

这对我来说没问题,这个例子对我来说很有意义:

service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
// Make sure a 'users' document exists for the requesting user before allowing any writes to the 'cities' collection
allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid))
// Allow the user to delete cities if their user document has the
// 'admin' field set to 'true'
allow delete: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
}
}
}

但然后它说

对于写入,您可以使用 getAfter() 函数访问 事务或一批写入完成之后但之前的文档 事务或批处理提交。

我可能仍然不完全理解这个概念。我的问题是:

  1. 为什么特别要用getAfter()进行事务或者批量写入,我们可以只用get()吗?
  2. 如果你必须使用 getAfter() 进行事务或批量写入,这是否意味着你仍然需要 get() 进行正常写入? 它们如何同时存在?

谢谢。

首先,请记住,写入的安全规则在该写入更改数据库中的任何内容之前启动。 这就是安全规则能够安全有效地拒绝访问的方式,而无需回滚任何已经发生的写入。

您引用的文档表明,getAfter 对于在整个事务的状态被记录之后(在内存中的一种"暂存"环境中)但在事务实际更改数据库之前检查数据库的内容很有用,每个人都可以看到。 这与get不同,因为get只查看数据库的实际内容,在事务最终提交之前。 简而言之,getAfter使用整个事务或批处理的整个暂存写入,而get使用数据库的实际现有内容。

您没有义务使用getAfter,如果get适合您的情况。

当您需要检查交易记录或批处理中可能已更改的其他文档,并且仍然有机会因规则失败而拒绝整个事务或批处理时,getAfter非常有用。 因此,例如,如果在单个事务中写入的两个文档必须具有一些共同的字段值才能保持一致,则需要使用getAfter来验证两者之间的相等性。get在这里没有帮助,因为它不知道事务中尚未编写的其他文档的任何信息。

另一方面,如果您的规则需要检查事务中的文档是否未更改现有文档(即正在检查的当前文档)中的字段,则get需要在事务写入该值之前获取该值。

最新更新