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

Javascript Firebase数据库-防止写入指定路径以外的所有路径,javascript,firebase,firebase-realtime-database,firebase-security,Javascript,Firebase,Firebase Realtime Database,Firebase Security,我有firebase设置和工作(提交表单数据客户端),但我试图添加一些规则和验证。只有一个路径,它是可公开写入的,但我想将其锁定,以便无法创建其他路径 我想我可以做到: { "rules": { "myPath": { ".read": "auth != null", ".write": true, ".validate": "newData.hasChildren([ 'name', 'email', 'agree

我有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"
 }
}
有效负载只是一个包含hasChildren字段的对象

可重现问题的有效负载对象:

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 },
      },
    };
您正在调用
push(…)
,它在您调用它的引用下创建一个新的子节点。因此属性(
agreeTerms
email
等)最终位于
/myPath/-LK….
下,验证希望它们立即位于
/myPath

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

第一个很简单:

const dataBase = firebase.database().ref('/myPath');
dataBase.set(payload, error => {
      if (error) {
        return console.log(`Error writing to database ${error}`);
      }
});
由于这将调用
set(…)
而不是push,因此数据直接写入
myPath
下,并与验证规则相匹配

第二种解决方案是使您的安全规则与代码匹配,这意味着您需要在规则中执行较低级别的验证。由于您事先不知道由
push()
生成的ID是什么,因此需要将其设置为所谓的“通配符规则”:

{
“规则”:{
“myPath”:{
“$pushId”:{
“.write”:正确,
“.validate”:“newData.haschilds(['name'、'email'、'agreeTerms'、'results'])”,
“name”:{.validate”:“newData.isString()&&newData.val().length<
100"},
“电子邮件:{.validate:”newData.isString()“},
“agreeTerms”:{.validate”:“newData.isString()&&newData.val().length<4”}
}
},
“.read”:“auth!=null”,
.write:“auth!=null”
}
}

在上面的示例中:
$pushId
下的规则适用于
/myPath
下的任何子节点。此逻辑适用于名称以
$
开头的任何规则。因此,它不必被称为
$pushId
,它也可以是
$child
或任何以
$
开头的东西。您能用硬编码的对象为有效负载进行复制吗?如果是这样,请更新您的问题以显示。@FrankvanPuffelen是的,我已将其添加到问题中。非常感谢!效果很好。我是firebase的新手,所以这确实帮助我更好地理解它。
const dataBase = firebase.database().ref('/myPath');
dataBase.set(payload, error => {
      if (error) {
        return console.log(`Error writing to database ${error}`);
      }
});
{
 "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"
 }
}