在Firebase实时数据库规则中验证匿名用户的显示名称

All*_*len 7 firebase firebase-security firebase-authentication firebase-realtime-database

我正在为匿名用户设置显示名称,并希望确保新值与此设置的显示名称匹配.以下规则失败:

"name": { ".validate": "newData.val() == auth.token.name" }

为什么是这样?该文档说,显示名称存储在auth.token.name.

以下是我的firebase规则的完整副本:

{
    "rules": {
    ".read": false,
    ".write": false,
    "messages": {
        ".read": true,
        "$message": {
            ".write": "auth != null",
            ".validate": "newData.hasChildren(['createdAt', 'text', 'user'])",

            "createdAt": { ".validate": "newData.val() == now" },
            "text": { ".validate": "newData.isString() && newData.val().length > 0" },
            "user": {
                ".validate": "newData.hasChildren(['_id', 'name'])",
                 "_id": { ".validate": "newData.val() == auth.uid" },
                 "name": { ".validate": "newData.val() == auth.token.name" },
            "$other": { ".validate": false }
        },
        "$other": { ".validate": false }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Ros*_*des 3

正如我在评论中提到的(摘自文档):

较浅的安全规则会覆盖较深层路径的规则。子规则只能向父节点已经声明的内容授予额外的权限。他们无法撤销读取或写入权限。

这意味着您将无法写入数据库,因为您已.write:false在数据库的根节点声明。您可能需要删除该行以获得如下结构:

{
    "rules": {
    ".read": false,
    "messages": {
        ".read": true,
        "$message": {
            ".write": "auth != null",
            ".validate": "newData.hasChildren(['createdAt', 'text', 'user'])",

            "createdAt": { ".validate": "newData.val() == now" },
            "text": { ".validate": "newData.isString() && newData.val().length > 0" },
            "user": {
                ".validate": "newData.hasChildren(['_id', 'name'])",
                 "_id": { ".validate": "newData.val() == auth.uid" },
                 "name": { ".validate": "newData.val() == auth.token.name" },
            "$other": { ".validate": false }
        },
        "$other": { ".validate": false }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

显示名称确实存储在auth.token.name变量下。但是,当您在规则模拟器上使用默认的“匿名身份验证”时,这会发送具有以下默认身份验证有效负载的请求:

{
  "provider": "anonymous",
  "uid": "N4EbtSX5HbM9JLjsW6hWT3NWzAx1"
}
Run Code Online (Sandbox Code Playgroud)

请注意,此有效负载下没有name指定,因此该auth.token.name变量为空,并且安全规则拒绝写入。

您可以在模拟器上使用自定义有效负载,只需将身份验证提供程序从“匿名”更改为“自定义”,它允许您编辑有效负载,因此您可以改用以下内容:

{
  "provider": "anonymous",
  "uid": "N4EbtSX5HbM9JLjsW6hWT3NWzAx1",
  "token":{
    "name": "Mike"
  }
}
Run Code Online (Sandbox Code Playgroud)

使用此身份验证有效负载,您在注释中提供的数据有效负载应该可以工作:

{ 
    "createdAt": { 
        ".sv": "timestamp" 
    }, 
    "text": "Test 1", 
    "user": 
    { 
        "_id": "48c83bf9-7354-4720-838f-8b68e0addd51", 
        "name": "Mike"
    }
}
Run Code Online (Sandbox Code Playgroud)