如何在Firebase(Swift)中使用安全规则限制子节点

时间:2016-09-22 02:24:11

标签: ios swift firebase firebase-security

我正在使用firebase开发基于Turn的游戏。我的游戏有游戏室,每个房间最多包含3个子节点。这些是Player1,Player2和当前用户计数。我的情况是,Player1创建了一个有2个子节点的房间(Player1 ID和当前用户数)。玩家1正在等待一个敌人。但是,如果其他2个玩家同时点击加入,则该房间将有3个玩家。如何使用安全规则来避免这种情况?

我的相关数据库部分如下文所示:

"QuickPlay3hanePlaying" : {
"ByVmFbUC6HS01v4SASeA2ev33zz1" : {
  "3s6TdUxImrNhMReJbS8kBh4I9im1" : {
    "IQ" : 1350,
    "date" : 1.474527951467337E9,
    "gizliSayi" : [ 1, 2, 3, 4, 5 ],
    "isReady" : 0,
    "isSiraBende" : 0,
    "isWin" : 0,
    "name" : "Emre Esen",
    "photoUrl" : "https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/1796656_10203231676898828_1482882234_n.jpg?oh=b1600006284e4e8ca9411d804c5571a2&oe=5880E580",
    "sonTahminim" : [ 1, 2, 3, 4, 5 ],
    "uid" : "3s6TdUxImrNhMReJbS8kBh4I9im1"
  },
  "ByVmFbUC6HS01v4SASeA2ev33zz1" : {
    "IQ" : 1280,
    "date" : 1.474527943420204E9,
    "gizliSayi" : [ 1, 2, 3, 4, 5 ],
    "isReady" : 0,
    "isSiraBende" : 1,
    "isWin" : 0,
    "name" : "Emot Emot",
    "photoUrl" : "https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/14225541_330456493965915_6052582248934611374_n.jpg?oh=35c26a6ea69a3266451a33908c7a060a&oe=586E13B1",
    "sonTahminim" : [ 1, 2, 3, 4, 5 ],
    "uid" : "ByVmFbUC6HS01v4SASeA2ev33zz1"
  },
  "userSayisi" : 2
}

}

创建房间代码块:

    func createRoom(){


    Model.sharedInstance.QuickPlayOdaAdi = Model.sharedInstance.userFirebaseID

    setPlayerInfo()

    let interval = NSDate().timeIntervalSince1970

    let info = ["photoUrl":Model.sharedInstance.userPictureUrl,
                "uid":Model.sharedInstance.userFirebaseID,
                "IQ":Model.sharedInstance.userIQ,
                "name":Model.sharedInstance.username,
                "isSiraBende":1,
                "gizliSayi":Model.sharedInstance.gizliSayi,
                "isReady":Model.sharedInstance.isReadyForPlaying,
                "isWin":Model.sharedInstance.isWin,
                "sonTahminim":Model.sharedInstance.rakipSonTahmini,
                "date":interval]


    Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.userFirebaseID).setValue(["userSayisi":1])

    Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.userFirebaseID).child(Model.sharedInstance.userFirebaseID).setValue(info)

    // uygulama kapatıldıgında remove olsun diye

    Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).child(Model.sharedInstance.userFirebaseID).onDisconnectRemoveValue()
    Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).child("userSayisi").onDisconnectRemoveValue()



    Model.sharedInstance.handleCreateRoom =  Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).observeEventType(.Value, withBlock: { (snapshot) in

        print("SnapCount: \(snapshot.childrenCount)")

        // usersayısı ve 1 kullanıcı ile snap sayısı 2 oluyor 1 kullanıcı için

        if snapshot.childrenCount == 3 {

            print("Game Start")




            Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).removeObserverWithHandle(Model.sharedInstance.handleCreateRoom)

            Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).updateChildValues(["userSayisi":2])


            let ilkEleman = snapshot.children.allObjects[0] as! FIRDataSnapshot

            let ikinciEleman = snapshot.children.allObjects[1] as! FIRDataSnapshot

            let ucuncuEleman = snapshot.children.allObjects[2] as! FIRDataSnapshot




            print(ucuncuEleman.key)

            if ilkEleman.key != Model.sharedInstance.userFirebaseID && ilkEleman.key != "userSayisi" {

                 print(ilkEleman.key)

                dispatch_async(GlobalBackgroundQueue, {

                    Model.sharedInstance.enemyName = ilkEleman.value!["name"] as! String
                    Model.sharedInstance.enemyIQ = ilkEleman.value!["IQ"] as! Int
                    Model.sharedInstance.enemyFirebaseID = ilkEleman.value!["uid"] as! String
                    Model.sharedInstance.enemyPictureUrl = ilkEleman.value!["photoUrl"] as! String



            Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])




                    dispatch_async(GlobalMainQueue, {

                        self.enemyNameLbl.text = Model.sharedInstance.enemyName
                        self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                        self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                    })

                })




                Model.sharedInstance.delay(2.5, closure: {
                    self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)



                })




            }
            else if ikinciEleman.key != Model.sharedInstance.userFirebaseID && ikinciEleman.key != "userSayisi" {


                 print(ikinciEleman.key)
                dispatch_async(GlobalBackgroundQueue, {

                    Model.sharedInstance.enemyName = ikinciEleman.value!["name"] as! String
                    Model.sharedInstance.enemyIQ = ikinciEleman.value!["IQ"] as! Int
                    Model.sharedInstance.enemyFirebaseID = ikinciEleman.value!["uid"] as! String
                    Model.sharedInstance.enemyPictureUrl = ikinciEleman.value!["photoUrl"] as! String



                    Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])



                    dispatch_async(GlobalMainQueue, {

                        self.enemyNameLbl.text = Model.sharedInstance.enemyName
                        self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                        self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                    })

                })



                Model.sharedInstance.delay(2.5, closure: {
                    self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)


                })

            }else{


                print(ikinciEleman.key)
                dispatch_async(GlobalBackgroundQueue, {

                    Model.sharedInstance.enemyName = ucuncuEleman.value!["name"] as! String
                    Model.sharedInstance.enemyIQ = ucuncuEleman.value!["IQ"] as! Int
                    Model.sharedInstance.enemyFirebaseID = ucuncuEleman.value!["uid"] as! String
                    Model.sharedInstance.enemyPictureUrl = ucuncuEleman.value!["photoUrl"] as! String



                    Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])



                    dispatch_async(GlobalMainQueue, {

                        self.enemyNameLbl.text = Model.sharedInstance.enemyName
                        self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                        self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                    })

                })



                Model.sharedInstance.delay(2.5, closure: {
                    self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)


                })


            }




        }else if snapshot.childrenCount == 2 {

            print("1 user waiting")

            Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["userSayisi":1])

        }



    }) { (error) in
        print(error)
    }


}

加入房间代码块:

    func joinRoom(){

    setPlayerInfo()



    Model.sharedInstance.quickPlayRoomPerGameRef.queryOrderedByChild("userSayisi").queryEqualToValue(1).queryLimitedToLast(1).observeSingleEventOfType(.Value, withBlock: { (snapshot) in



       if snapshot.exists(){




       let odaAdi = snapshot.children.allObjects[0] as! FIRDataSnapshot


        Model.sharedInstance.QuickPlayOdaAdi = odaAdi.key

        let interval = NSDate().timeIntervalSince1970

        let info = ["photoUrl":Model.sharedInstance.userPictureUrl,
            "uid":Model.sharedInstance.userFirebaseID,
            "IQ":Model.sharedInstance.userIQ,
            "name":Model.sharedInstance.username,
            "isSiraBende":0,
            "gizliSayi":Model.sharedInstance.gizliSayi,
            "isReady":Model.sharedInstance.isReadyForPlaying,
            "isWin":Model.sharedInstance.isWin,
            "sonTahminim":Model.sharedInstance.rakipSonTahmini,
            "date":interval
        ]



      Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).child(Model.sharedInstance.userFirebaseID).setValue(info)

        Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).removeObserverWithHandle(Model.sharedInstance.handleJoinRoom)

        Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).child(Model.sharedInstance.userFirebaseID).onDisconnectRemoveValue()
        Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).child("userSayisi").onDisconnectRemoveValue()



        Model.sharedInstance.quickPlayRoomPerGameRef.child(odaAdi.key).observeSingleEventOfType(.Value, withBlock: { (snapshot) in

            print("SnapCount: \(snapshot.childrenCount)")



                let ilkEleman = snapshot.children.allObjects[0] as! FIRDataSnapshot

                let ikinciEleman = snapshot.children.allObjects[1] as! FIRDataSnapshot

                let ucuncuEleman = snapshot.children.allObjects[2] as! FIRDataSnapshot





                if ilkEleman.key != Model.sharedInstance.userFirebaseID && ilkEleman.key != "userSayisi" {

                    print(ilkEleman.key)

                    dispatch_async(GlobalBackgroundQueue, {

                        Model.sharedInstance.enemyName = ilkEleman.value!["name"] as! String
                        Model.sharedInstance.enemyIQ = ilkEleman.value!["IQ"] as! Int
                        Model.sharedInstance.enemyFirebaseID = ilkEleman.value!["uid"] as! String
                        Model.sharedInstance.enemyPictureUrl = ilkEleman.value!["photoUrl"] as! String



                        Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])



                        dispatch_async(GlobalMainQueue, {

                            self.enemyNameLbl.text = Model.sharedInstance.enemyName
                            self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                            self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                        })

                    })

                    Model.sharedInstance.delay(2.5, closure: {



                        self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)


                    })



                }
                else if ikinciEleman.key != Model.sharedInstance.userFirebaseID && ikinciEleman.key != "userSayisi"{


                    print(ikinciEleman.key)
                    dispatch_async(GlobalBackgroundQueue, {

                        Model.sharedInstance.enemyName = ikinciEleman.value!["name"] as! String
                        Model.sharedInstance.enemyIQ = ikinciEleman.value!["IQ"] as! Int
                        Model.sharedInstance.enemyFirebaseID = ikinciEleman.value!["uid"] as! String
                        Model.sharedInstance.enemyPictureUrl = ikinciEleman.value!["photoUrl"] as! String



                        Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])


                        dispatch_async(GlobalMainQueue, {

                            self.enemyNameLbl.text = Model.sharedInstance.enemyName
                            self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                            self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                        })

                    })

                    Model.sharedInstance.delay(2.5, closure: {




                        self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)


                    })

                }
                else{

                    print(ucuncuEleman.key)
                    dispatch_async(GlobalBackgroundQueue, {

                        Model.sharedInstance.enemyName = ucuncuEleman.value!["name"] as! String
                        Model.sharedInstance.enemyIQ = ucuncuEleman.value!["IQ"] as! Int
                        Model.sharedInstance.enemyFirebaseID = ucuncuEleman.value!["uid"] as! String
                        Model.sharedInstance.enemyPictureUrl = ucuncuEleman.value!["photoUrl"] as! String



                        Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])


                        dispatch_async(GlobalMainQueue, {

                            self.enemyNameLbl.text = Model.sharedInstance.enemyName
                            self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                            self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                        })

                    })

                    Model.sharedInstance.delay(2.5, closure: {




                        self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)


                    })


                }







        }) { (error) in
            print(error)
        }




       }else{

        self.createRoom()

        }


        }) { (error) in

            print(error)
    }

}

1 个答案:

答案 0 :(得分:0)

这可以在您的安全规则中处理,但您必须稍微更改数据库结构。而不是你现在拥有的东西,你必须做这样的事情:

"QuickPlay3hanePlaying" : {
  "ByVmFbUC6HS01v4SASeA2ev33zz1" : {
    "Player1" : {
      "3s6TdUxImrNhMReJbS8kBh4I9im1" : {
        "IQ" : 1350,
        ...
        "uid" : "3s6TdUxImrNhMReJbS8kBh4I9im1"
      },
    },
    "Player2" : {
      "ByVmFbUC6HS01v4SASeA2ev33zz1" : {
        "IQ" : 1280,
        ...
        "uid" : "ByVmFbUC6HS01v4SASeA2ev33zz1"
      },
    },
    "userSayisi" : 2
  }

您的安全规则如下所示:

{
"rules": {
  "QuickPlay3hanePlaying": {
    "$id": {
      "player1": {".validate": true},
      "player2":{".validate": true},
      "userSayisi": {".validate": true},
      "$other": {".validate": false}
      }
    }
  }
}

更改数据库结构的原因是因为您在某个位置的安全规则中只能有1个通配符键。