Firestore安全规则-如何防止对特定字段进行修改

时间:2018-09-15 10:44:16

标签: firebase google-cloud-firestore firebase-security-rules

假设我们有一个名为todos的Firestore集合,其中每个待办事项都将如下所示:

{
    name: "Buy milk",
    completed: false,
    user: "eYtGDHdfgSERewfqwEFfweE" // some user's uid
}

现在,我想在更新过程中防止对user字段进行修改(换句话说,将该字段设置为只读)。

相信我,我已经完成了研究。我的update规则如下:

allow update: if request.auth.uid == resource.data.user
              //&& !request.writeFields.hasAny(["user"]);
              //&& !(request.writeFields.hasAny(["user"]));
              //&& !request.resource.data.keys().hasAny(["user"]);
              //&& !('user' in request.resource.data);
              //&& ('user' in request.resource.data) == false;
              //&& !('user' in request.writeFields);

没有(上述注释)。它们都会导致错误:Error: Missing or insufficient permissions.

但是...

它变得更加有趣!因为如果我们将上述某些规则用于阳性结果(又称true),它们将起作用!

例如,这个完美(假设我们在请求中包含user字段)

allow update: if request.resource.data.keys().hasAny(["user"]) == true;

但此操作无效(假设我们在请求中不包含user字段):

allow update: if request.resource.data.keys().hasAny(["user"]) == false;

有人可以解释一下这是怎么回事吗?难道这实际上是Firestore中的错误?

2 个答案:

答案 0 :(得分:0)

在“ Cloud Firestore安全规则的编写条件”部分的“数据验证”示例#2

{id: "0", regno: "01107402042", appno: "10001", certid: "1", file_name: "9bfe44de3ddb583778d2b641bdb6b79f.pdf", …}

那么service cloud.firestore { match /databases/{database}/documents { // Make sure all cities have a positive population and // the name is not changed match /cities/{city} { allow update: if request.resource.data.population > 0 && request.resource.data.name == resource.data.name; } } } 应该为您工作吗? CMIIW

参考:https://firebase.google.com/docs/firestore/security/rules-conditions#data_validation

答案 1 :(得分:0)

当您更新文档时,安全规则会将更新产生的文档与安全规则的条件进行比较。这意味着如果某个字段存在于服务器上的文档中,但不存在于您在更新中推送的数据中,则安全规则将从更新中的旧数据中看到该字段。例如:

在服务器上的文档存储中:

{
  reviewerID: sam123,
  title: "It sucks",
  description: "Because it does",
  rating: 1
}

然后你的更新是:

{
  description: "but actually it's not so bad",
  rating: 3
}

那么安全规则在request.resource.data中看到的是:

{
  reviewerID: sam123,
  title: "It sucks",
  description: "but actually it's not so bad",
  rating: 3
}

这意味着即使更新没有将更改推送到 reviewerIDtitle,这些字段确实存在于您正在评估的数据中。

为了确保数据不变,您需要将新数据与旧数据进行比较:

request.resource.data.reviewerID == resource.data.reviewerID

行:

!request.resource.data.keys().hasAny(["user"]);

防止数据存在于文档中是正确的。它不是允许它存在但使其不可变的东西。

见:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}

来自:

https://firebase.google.com/docs/firestore/security/rules-conditions#data_validation

和:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to create a document only if that document does *not*
    // contain an average_score or rating_count field.
    match /restaurant/{restId} {
      allow create: if (!request.resource.data.keys().hasAny(
        ['average_score', 'rating_count']));
    }
  }
}

来自:

https://firebase.google.com/docs/firestore/security/rules-fields#forbidding_specific_fields_in_new_documents