当observeSingleEvent时Swift Firebase规则权限被拒绝
Posted
技术标签:
【中文标题】当observeSingleEvent时Swift Firebase规则权限被拒绝【英文标题】:Swift Firebase Rule Permissions Denied when observeSingleEvent 【发布时间】:2018-08-09 11:22:58 【问题描述】:我正在开发一个应用程序,让教师可以记录学生的课程。使用 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 数据库的快照供参考:
有人知道我的规则有什么问题吗?也将不胜感激如何处理权限被拒绝的结果。
【问题讨论】:
是DataService.ds.REF_SCHOOLS
指向Schools
还是School/Some_school_ID
?
指向 Database.database().reference().child("Schools")
【参考方案1】:
您的代码正在尝试从/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。
【讨论】:
以上是关于当observeSingleEvent时Swift Firebase规则权限被拒绝的主要内容,如果未能解决你的问题,请参考以下文章
第一次调用时捕获 Firebase 实时observeSingleEvent 数据失败