当SwiftSbase事件发生时,Swift Firebase规则权限被拒绝

时间:2018-08-09 11:22:58

标签: ios swift firebase firebase-realtime-database firebase-security-rules

我正在开发一个应用程序,该应用程序允许老师记录他们的学生的课程。使用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数据库的快照供参考:

enter image description here

有人知道我的规则有什么问题吗?同样将理解如何处理许可拒绝结果。

1 个答案:

答案 0 :(得分:0)

您的代码正在尝试从/Schools进行读取,但是您的规则并未授予任何人从/Schools进行读取的权限。因此,Firebase会正确拒绝读取。

我有一种感觉,您希望读取操作会自动过滤结果,以便仅返回用户有权访问的学校节点(/Schools/$schoolId)。但这不是Firebase安全规则的工作原理:rules cannot be used to filter data

对于开发人员开始使用Firebase的服务器端安全规则,这是造成混淆的常见原因,因此,我建议您退出以前的questions mentioning "rules are not filters"


如今, 是一种获取过滤数据的方式,而无需授予用户访问所有Schools的权限。为此,您将需要:

  1. 使用查询仅请求您应该有权访问的学校。
  2. 确认您的安全规则中的/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 valueFirebase Query Double Nested