Firebase:根据用户角色设置安全规则

Mar*_*coS 24 firebase firebase-security

我想根据用户角色在Firebase中实现"编写"安全规则.
我的数据结构是这样的:

+ myapp
  + users
    + john
      + email: "john@mail.com"
      + roles
        + administrator: true
    + mary
      + email: "mary@mail.com"
      + roles
        + moderator: true
    + ...
  + documents
    + -JVmo6wZM35ZQr0K9tJu
      + ...
    + -JVr56hVTZxlAI5AgUaS
      + ...
    + ...
Run Code Online (Sandbox Code Playgroud)

我希望 - 例如 - 只有管理员用户才能编写文档.
这些是我来的规则:

{
  "rules": {
    ".read": true,
    "$documents": {
      ".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但它不起作用:管理员用户甚至都不能写文档......
我对Firebase安全规则的理解是否完全有缺陷?

更新:就在Jenny回答之前(不管你信不信:-),我确实实现了他提供的完全相同的解决方案(当然基于Kato的评论).
虽然,做了一些测试,我不能让规则结构

{
  "rules": {
    "documents" {
      "$document" {
        ".read": "root.child('users').child(auth.uid).child('roles').child('documents').child('read').val() === true",
        ".write": "root.child('users').child(auth.uid).child('roles').child('documents').child('write').val() === true"
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

工作...我总是得到这样的警告:

"FIREBASE WARNING: on() or once() for /documents failed: Error: permission_denied: Client doesn't have permission to access the desired data. "
Run Code Online (Sandbox Code Playgroud)

所以我想出了这个结构,相反:

{
  "rules": {
    "documents" {
      ".read": "root.child('users').child(auth.uid).child('roles').child('documents').child('read').val() === true",
      ".write": "root.child('users').child(auth.uid).child('roles').child('documents').child('write').val() === true"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

对我来说确实有效:如果我将一个角色/客户/读取节点设置为true,他可以读取所有文档,否则他不能(和写入相同).

我现在怀疑的是:

  • 为什么我不能让第一条规则(加藤建议)有效?
  • 你看到规则中有任何可能的安全漏洞,就像我想到的那样吗?
  • 使用"$"变量是必要/有用的规则,即使您不必根据它的键允许/拒绝每个单个文档的可读性/可写性,但您只想允许/拒绝节点的可读性/可写性为整个?

mim*_*ing 27

根据您的用户记录的名称,它们不匹配auth.uid,这可能是一个简单的登录 ID,例如twitter:2544215.

首先调整要通过Simple Login uid存储的用户:

+ myapp
  + users
    + twitter:2544215
      + email: "john@mail.com"
      + roles
        + administrator: true
    + twitter:2544216
      + email: "mary@mail.com"
      + roles
        + moderator: true
    + ...
  + documents
    + -JVmo6wZM35ZQr0K9tJu
      + ...
    + -JVr56hVTZxlAI5AgUaS
      + ...
    + ...
Run Code Online (Sandbox Code Playgroud)

接下来,添加安全规则,以便管理员可以访问documents.这里有几个选项,具体取决于您的具体用例.

  1. 为管理员提供对每个文档内容的写访问权限:

    {
      "rules": {
        "documents": {
          "$documents": {
            ".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
          }
        }
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 或者,或者,让他们访问整个集合:

    {
      "rules": {
        "documents": {
          ".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
        }
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

这两者之间的差异$documents是将安全规则进一步移动到层次结构中的变量.

(这主要只是@Kato对答案表的评论汇总)