Firebase Firestore安全规则-如何防止修改特定字段
假设我们有一个名为Firebase Firestore安全规则-如何防止修改特定字段,firebase,google-cloud-firestore,firebase-security,Firebase,Google Cloud Firestore,Firebase Security,假设我们有一个名为todo的Firestore集合,其中每个todo看起来如下: { name: "Buy milk", completed: false, user: "eYtGDHdfgSERewfqwEFfweE" // some user's uid } allow update: if request.auth.uid == resource.data.user //&& !request.writeFields.h
todo
的Firestore集合,其中每个todo看起来如下:
{
name: "Buy milk",
completed: false,
user: "eYtGDHdfgSERewfqwEFfweE" // some user's uid
}
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);
现在,我想防止在更新过程中修改用户
字段(换句话说,使该字段只读)
相信我,我已经做了研究。我的update
规则如下所示:
{
name: "Buy milk",
completed: false,
user: "eYtGDHdfgSERewfqwEFfweE" // some user's uid
}
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);
上述(已注释掉的)工作中无一项。它们都会导致错误:错误:缺少或权限不足。
但是
它变得更有趣了!因为如果我们比较上面的一些规则来获得积极的结果(akatrue
),它们就会起作用
例如,这个可以完美地工作(假设我们在请求中包含user
字段):
但是这个不起作用(假设请求中不包含用户字段):
谁能解释一下这里发生了什么事?是否可能这实际上是Firestore中的一个bug?在“编写云Firestore安全规则的条件”部分“数据验证”示例2
所以request.resource.data.user==resource.data.user
应该为您工作吗?CMIIW
参考:在“云Firestore安全规则的编写条件”部分“数据验证”示例2
所以request.resource.data.user==resource.data.user
应该为您工作吗?CMIIW
Ref:更新文档时,安全规则会将更新后的文档与安全规则的条件进行比较。这意味着,如果服务器上的文档中存在某个字段,但在更新中推送的数据中不存在该字段,则安全规则将从更新中的旧数据中看到该字段。例如:
在服务器上的文档存储中:
{
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
}
这意味着,即使更新没有将更改推送到reviewerID
或title
中,这些字段也确实存在于您正在评估的数据中
要确保数据不变,您需要将新数据与旧数据进行比较:
request.resource.data.reviewerID==resource.data.reviewerID
该行:
!request.resource.data.keys().hasAny([“user”])代码>
在阻止文档中存在数据方面是正确的。它不是允许它存在但使它不变的东西
见:
发件人:
以及:
发件人:
更新文档时,安全规则会将更新后的文档与安全规则的条件进行比较。这意味着,如果服务器上的文档中存在某个字段,但在更新中推送的数据中不存在该字段,则安全规则将从更新中的旧数据中看到该字段。例如:
在服务器上的文档存储中:
{
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
}
这意味着,即使更新没有将更改推送到reviewerID
或title
中,这些字段也确实存在于您正在评估的数据中
要确保数据不变,您需要将新数据与旧数据进行比较:
request.resource.data.reviewerID==resource.data.reviewerID
该行:
!request.resource.data.keys().hasAny([“user”])代码>
在阻止文档中存在数据方面是正确的。它不是允许它存在但使它不变的东西
见:
发件人:
以及:
发件人:
是的,我也用这个作为解决办法。但这样,您必须在每个请求中包含user
字段,例如set({user:firebase.auth().currentUser.uid,completed:true})
。如果你不这样做,你会得到一个错误。我希望能够完全不包含这个字段,例如set({completed:true})
您可以使用set({completed:true},{merge:true})或update({completed:true})哦,伙计,您是对的。我非常关注那些安全规则,但实际上我使用了错误的方法。。。谢谢如果最初未设置user
字段,则此解决方案不起作用。是的,我也将此用作解决方法。但这样,您必须在每个请求中包含user
字段,例如set({user:firebase.auth().currentUser.uid,completed:true})
。如果你不这样做,你会得到一个错误。我希望能够完全不包含这个字段,例如set({completed:true})
您可以使用set({completed:true},{merge:true})或update({completed:true})哦,伙计,您是对的。我非常关注那些安全规则,但实际上我使用了错误的方法。。。谢谢如果最初未设置用户
字段,则此解决方案不起作用。