Firestore 规则使用 Flutter 客户端验证时间戳

Posted

技术标签:

【中文标题】Firestore 规则使用 Flutter 客户端验证时间戳【英文标题】:Firestore Rules verify timestamp with a Flutter client 【发布时间】:2018-12-29 14:33:57 【问题描述】:

我想通过客户端发送 Firestore 文档的创建时间,并使用 Firestore 规则验证时间以避免 Cloud Functions 调用(定价)。

场景

我正在根据这样的 Firestore 规则测试来自客户端的请求:

allow create: if request.resource.data.TIMEFIELD == request.time;

请求包含一个带有时间戳TIMEFIELD,就像request.time一样。

问题

显然请求时间和我在发送请求之前设置为字段的时间不相等,这使得无法进行比较。

以下是文档中request.time 的定义。

When the request was received by the service.

不知道有没有办法在文档中设置字段等于request.time

由于an issue with Flutter,我无法使用服务器端时间戳。 因此,我需要知道如何使用 Firestore 规则验证客户端时间戳,例如 time.now

【问题讨论】:

允许创建:如果 request.resource.data.TIMEFIELD == request.time;这背后有什么原因吗?为什么要验证时间? @AngusTay 因为时间戳对产品很重要,没有人应该能够操纵时间。我认为这是 Firebase 安全规则背后的主要原因。 这个问题似乎是 Flutter 特有的——也许自 2018 年以来就已修复?如果是这样,您是否愿意在标题中提及 Flutter 并将其添加为标签?也许整个问题都已解决,在这种情况下,这个问题只能作为历史证据。 【参考方案1】:

您可以使用Timestamp 将约束添加到时间字段 (docs)。

以下是如何确保更改在一定秒数内的示例:

function withinSeconds(secs) 
  return request.resource.data.TIMEFIELD.seconds() - request.time.seconds() <= secs
    && request.resource.data.TIMEFIELD.seconds() - request.time.seconds() >= -secs

编辑

以上是用于将值设置在request.time的阈值内。

与此同时,您也可以只使用 REST API。只需发出一个包含updatetransformwrite 请求。 transform 是您设置服务器时间戳的位置。 Here 是帮助理解如何构建请求的工具。

【讨论】:

是的,我误解了这个问题。我刚刚更新了答案。 @creativecreatorormaybenot here 是我之前用如何使用 REST API 插入时间戳的示例写的答案。它可能会帮助您了解有效负载结构。您也可以只执行 Web SDK 并查看“网络”(在控制台中)选项卡以查看生成的有效负载。 这不是(最好的)方法。 FieldValue.serverTimestamp() 将提供一个完全准确的时间戳。【参考方案2】:

这已在 Cloud Firestore 的 Flutter 插件中实现:

FieldValue.serverTimestamp()

将其用作字段的值将在服务器端为该字段分配一个等于request.time 的时间戳。

您可以在API referencecloud_firestore 中找到更多相关信息。

【讨论】:

【参考方案3】:

您首先必须记住创建(或上次更新)时间戳:

firestore().collection("items").add(
    ....
    created: firebase.firestore.FieldValue.serverTimestamp()
);

为了让客户端知道您稍后尝试比较的时间戳。

【讨论】:

这个问题没有提到 Flutter,也没有提到任何平台......虽然这将是 JS 文档(证明这个值至少存在于服务器端):firebase.google.com/docs/reference/js/… @creativecreator 或者可能没有提供访问权限的 Dart/Flutter 插件:github.com/pauldemarco/plugins/tree/master/packages/… ...您的业务逻辑应该考虑,服务器时间戳才是真正重要的(可能有一些相对于客户端时间戳的偏移量)。基本上,您需要更新文档,然后在客户端更新新的时间戳。只需添加一个更新一个和另一个的函数,比较这两者。类似于SyncAdapter

以上是关于Firestore 规则使用 Flutter 客户端验证时间戳的主要内容,如果未能解决你的问题,请参考以下文章

为啥这些 Firestore 规则不适用于 Flutter Firebase 插件?

Flutter & Firebase - FirebaseFirestoreException:如果我按照以下方式制定了 Firebase 规则,如何获得使用 Firestore 中所有数据的

Flutter 和 Firestore 在请求中没有用户信息

如何使用 Flutter 防御性地从 Firestore 请求数据

Firestore 安全规则:更新已禁用,但更新完美

Flutter 和 Firestore 基于位置的查询和数据结构