我正在开发一个应用程序,该应用程序允许老师记录他们的学生的课程。使用Firebase规则我想允许教师访问某些学校。我有以下规则:
{
"rules": {
"Schools" : {
"$schoolId" : {
".read" : "data.child('Teachers').hasChild(auth.uid)",
".write" : "data.child('Teachers').hasChild(auth.uid) ||
root.child('User').child(auth.uid).child('Invitation').exists()"
}
},
"Users" : {
"$uid" : {
".read" : "auth.uid === $uid",
".write": "auth.uid === $uid"
}
}
}
}
在模拟器中,一切正常,但是在触发以下内容时,所有学校均被拒绝所有权限。
DataService.ds.REF_SCHOOLS.observeSingleEvent(of: .value) { (snapshot) in
MySchools.mySchoolKeyList.removeAll()
MySchools.mySchoolList.removeAll()
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
for snap in snapshot {
if let recordDict = snap.value as? Dictionary<String, AnyObject> {
if let name = (recordDict["SchoolName"] as? String) {
MySchools.mySchoolList.append(name)
}
MySchools.mySchoolKeyList.append(snap.key)
}
}
if MySchools.mySchoolList.isEmpty {
MySchools.mySchoolList.append("You do not belong to any schools.")
}
}
}
以下是Firebase数据库的快照供参考:
有人知道我的规则有什么问题吗?同样将理解如何处理许可拒绝结果。
答案 0 :(得分:0)
您的代码正在尝试从/Schools
进行读取,但是您的规则并未授予任何人从/Schools
进行读取的权限。因此,Firebase会正确拒绝读取。
我有一种感觉,您希望读取操作会自动过滤结果,以便仅返回用户有权访问的学校节点(/Schools/$schoolId
)。但这不是Firebase安全规则的工作原理:rules cannot be used to filter data。
对于开发人员开始使用Firebase的服务器端安全规则,这是造成混淆的常见原因,因此,我建议您退出以前的questions mentioning "rules are not filters"。
如今, 是一种获取过滤数据的方式,而无需授予用户访问所有Schools
的权限。为此,您将需要:
/Schools
允许此查询。有关此示例,请参阅文档中的query based rules。
代码应如下所示:
let query = DataService.ds.REF_SCHOOLS.queryOrdered(byChild: "Teachers/"+uid).queryValue(equalTo: true);
query.observeSingleEvent(of: .value) { (snapshot) in
...
但是问题是您需要为每位老师定义一个索引。尽管从技术上讲这是可行的,但会导致索引数量不合理。
事后看来:您当前的数据结构可让您有效地找到特定学校的老师。但是,它不允许您有效地找到特定教师的学校。
要有效地允许查找特定教师的学校,请在数据库中添加一个将学校映射到每个教师的附加数据结构。例如
teacherSchools
teacherUid1
schoolId1: true
schoolId2: true
teacherUid2
schoolId2: true
schoolId3: true
使用此结构,您可以轻松读取教师的所有学校ID,然后加载每所学校。自Firebase pipelines the requests over a single connection起,此加载速度比大多数开发人员的预期要快得多。
有关此方法的详细说明,请参见Firebase query if child of child contains a value和Firebase Query Double Nested。