【问题标题】:security rules to allow update of specific fields允许更新特定字段的安全规则
【发布时间】:2020-01-28 07:11:02
【问题描述】:

我是安全规则的新手。我必须编写安全规则来防止用户更新除一个字段之外的文档。

假设我有一个文档

{ 字段1:一个, 字段2:两个, 字段3:三个, . . . 场:n }

登录的用户应该只能更新 field2。 使用 Firestore 安全规则。

【问题讨论】:

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


【解决方案1】:

安全规则中没有明确的方式来验证正在发生的更新。但是您可以做的是在写操作之前之后验证文档中的数据。通过比较这两者,并了解文档可以包含哪些字段,您可以确保只有特定字段可以更新。

我经常在我的安全规则中使用这个小助手功能:

function isUnmodified(key) {
  return request.resource.data[key] == resource.data[key]
}

顾名思义,它确保在此写入请求中不修改某个键/字段。例如,此规则只允许用户更新他们的个人资料文档,只要他们不修改 name 字段(除非他们是管理员):

allow update: if isAdmin(request) || 
  (request.auth.uid == uid && isUnmodified(request, resource, 'name'));

我也有这个辅助函数,它检查特定字段是否存在:

function isNotExisting(key) {
  return !(key in request.resource.data) && (!exists(resource) || !(key in resource.data));
}

这很重要,因为有时您希望允许一个字段只写入一次,或者只允许在它已经存在的情况下对其进行更新。有时我为此使用isNotExisting,但我发现自己这些天更多地使用更精细的操作(createupdate)而不是聚合write 规则。

最后,您可以要求某些字段,如以下创建规则:

  allow create: if request.auth.uid == uid &&
    request.resource.data.keys().hasOnly(['lastIndex', 'lastUpdated']) &&
    request.resource.data.keys().hasAll(['lastIndex', 'lastUpdated']) 

因此,如果用户指定了lastIndexlastUpdated 字段,则他们只能创建配置文件文档。如果他们指定了任何额外的字段,或者指定了更少的字段,则创建将被拒绝。

现在有了这些知识,我们可以回到您的需求,看看如何实现它。如前所述,您需要在每个单独的字段上做出声明,而不需要在其中使用通配符。因此,如果您的文档包含三个字段(field1field2field3),它们必须全部存在,并且用户只能更新 field2,则类似于:

allow update: if request.resource.data.keys().hasAll(['field1', 'field2', 'field2']) &&
  isUnmodified('field1')) && isUnmodified('field3'));

现在可能有一种更短的方法来执行此操作,方法是使用此处显示的 set 和 map diff 操作:https://firebase.google.com/support/release-notes/security-rules#february_13_2020 like:

// This rule only allows updates where "a" is the only field affected
allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(["a"]);

【讨论】:

  • 哇!关于 isUnmodified 的快速问题,您的调用如何接受 3 个参数和函数只有 1 个? requestresource 是否在 isUnmodified 中被吸收并提供,而无需在函数声明中明确定义它们?
  • 糟糕,这是复制/粘贴/忘记修改。我经常明确地传入requestresource,但是(取决于您定义函数的位置)很少需要,因为它们是范围的一部分。所以我倾向于在 Stack Overflow 上共享功能时删除它们。我是为isUnmodified 做的,但忘记了isNotExisting
  • 我想还有其他的魔法,谢谢弗兰克。超级酷的方法^^
【解决方案2】:

如果您更喜欢指定哪些字段可以编辑的方法,我发现本教程中的一个部分很有帮助:Intermediate topics in Firebase Security Rules - Firecasts

// Make sure the request has only the specified allowed fields    
function editingOnlyAllowedFields(allowedFields) {
    let editedKeys = request.resource.data.diff(resource.data).affectedKeys();
    return editedKeys.hasOnly(allowedFields);
}
// Then, you can specify which fields you want to be updatable
allow update: editingOnlyAllowedFields(["field1", "field2"]);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 2019-03-12
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    相关资源
    最近更新 更多