Firebase数据库 - 防止写入指定的路径以外的所有路径

时间:2018-01-12 15:16:57

标签: javascript firebase firebase-realtime-database firebase-security

我有firebase设置和工作(提交表单数据客户端)但我试图添加一些规则和验证。只有一条路径,它是可公开写入的,但我想将其锁定,以便不能创建其他路径。

我以为我能做到:

{
 "rules": {
   "myPath": {
     ".read": "auth != null",
     ".write": true,
     ".validate": "newData.hasChildren([
       'name',
       'email',
       'agreeTerms',
       'results',
     ])",
   "name": {".validate": "newData.isString() && newData.val().length < 
   100"},
  "email": {".validate": "newData.isString()"},
  "agreeTerms": {".validate": "newData.isString() && newData.val().length < 4"}
  },
  ".read": "auth != null",
  ".write": "auth != null"
 }
}

这适用于模拟器,但当我尝试提交表单时,它表示拒绝访问。

任何人都可以看到我做错了什么吗?所有帮助表示赞赏。

哦,提交数据的代码是:

const dataBase = firebase.database().ref('/myPath');
dataBase.push(payload, error => {
      if (error) {
        return console.log(`Error writing to database ${error}`);
      }
      //worked!!!
});

payload只是一个包含hasChildren字段的对象。

可以重现问题的Payload对象:

const payload = {
      agreeTerms: 'yes',
      email: 'terry@bingbong.com',
      name: 'Terry Bing',
      results: {
        q1: { score: 0, time: 0 },
        q2: { score: 0, time: 0 },
        q3: { score: 0, time: 0 },
        q4: { score: 0, time: 0 },
        q5: { score: 0, time: 0 },
      },
    };

1 个答案:

答案 0 :(得分:1)

您正在调用push(...),它会在您调用它的引用下创建一个新的子节点。因此,属性(agreeTermsemail等)最终位于/myPath/-LK....下,验证会立即将其置于/myPath下。

两种可能的修复方法:使用set(...)或修改规则以包含推送ID。

第一个很简单:

const dataBase = firebase.database().ref('/myPath');
dataBase.set(payload, error => {
      if (error) {
        return console.log(`Error writing to database ${error}`);
      }
});

由于这会调用set(...)而不是推送,因此数据直接写在myPath下并与验证规则匹配。

第二种解决方案是使您的安全规则与代码匹配,这意味着您需要在规则中低一级进行验证。既然你事先并不知道push()生成的ID是什么,你需要将其作为所谓的“通配符规则”:

{
 "rules": {
   "myPath": {
     "$pushId": {
       ".write": true,
       ".validate": "newData.hasChildren(['name', 'email', 'agreeTerms', 'results'])",
     "name": {".validate": "newData.isString() && newData.val().length < 
   100"},
    "email": {".validate": "newData.isString()"},
    "agreeTerms": {".validate": "newData.isString() && newData.val().length < 4"}
    }
  },
  ".read": "auth != null",
  ".write": "auth != null"
 }
}

在上文中:$pushId下的规则适用于/myPath下的任何子节点。此逻辑适用于名称以$开头的任何规则。因此,它不必被称为$pushId,它也可以是$child或以$开头的任何其他内容。