我有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 },
},
};
答案 0 :(得分:1)
您正在调用push(...)
,它会在您调用它的引用下创建一个新的子节点。因此,属性(agreeTerms
,email
等)最终位于/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
或以$
开头的任何其他内容。