检查唯一用户名时,Firebase 权限被拒绝



我想检查用户名是否已在使用中。当当前用户没有"用户名"的子级时,将调用此函数:

func createUsername()
{
    let userID = FIRAuth.auth()?.currentUser?.uid
    FIRDatabase.database().reference().updateChildValues([
        "users/(userID!)/username": username.text!,
        "usernames/(username.text!)": userID!
        ], withCompletionBlock: { (error, reference) in
            if (error != nil) {
                print("disallowed")
                // Write was disallowed because username exists
            }
    })
}

结合此规则:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid",
        "username": {
      ".read": true,
          ".write": "!data.exists() && newData.exists()",
          ".validate": "newData.isString()"
        }
      }
    },
    "usernames": {
      "$username": {
        ".read": true,
        ".write": "!data.exists() && newData.exists()",
        ".validate": "newData.isString() && newData.val() == root.child('users/' + auth.uid + '/username').val()"
      }
    }
  }
}

我从以下方面得到答案:https://groups.google.com/forum/#!topic/firebase-talk/dA1Lkykd-tk我收到此错误消息:

[Firebase/Database][I-RDB03812] updateChildValues: at/failed: permission_denied

我不确定为什么这行不通。我也尝试了这个答案: 火基安卓 :使用户名唯一 但这对我不起作用。规则有问题,但我不知道是什么。

更新,规则变化不大,仍然相同的错误:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid",
        "username": {
      ".read": true,
          ".write": "!data.exists() && newData.exists()",
          ".validate": "newData.isString()"
        }
      }
    },
    "usernames": {
      "$username": {
        ".read": true,
        ".write": "!data.exists() && newData.exists()",
        ".validate": "newData.isString() && newData.val() == newData.parent().parent().child('users/' + auth.uid + '/username').val()"
      }
    }
  }
}

我也更改了 parent(( 的东西,但它也不起作用。我换成了4个家长,0个家长。同样的错误。

更新:问题来自此验证规则:

".validate": "newData.isString() && newData.val() == root.child('users/' + auth.uid + '/username').val()"

您正在将新数据与当前根进行比较。由于用户刚刚创建/users/$uid因此尚不存在。

您要做的是将新数据与用户节点进行比较。要访问此节点,您应该在比较时从newData导航到根:

".validate": "newData.isString() && 
  newData.val() == newData.parent().parent().child('users/' + auth.uid + '/username').val()"

我将在下面留下我之前的回复,因为它可能对学习如何解决此类问题很有用。

我只是将您的规则粘贴到我的项目中,稍微简化了它们,并毫无问题地使用了您的代码。我不确定你为什么遇到问题。

代码:

    FIRAuth.auth()?.signInAnonymously(completion: { (user, error) in
        let username = "puf"
        let userID = FIRAuth.auth()?.currentUser?.uid
        self.ref.child("42188459").updateChildValues([
            "users/(userID!)/username": username,
            "usernames/(username)": userID!
        ], withCompletionBlock: { (error, reference) in
            if (error != nil) {
                print("disallowed")
                // Write was disallowed because username exists
            }
        })
    })

规则代码段:

  "users": {
    "$uid": {
      ".write": "$uid === auth.uid",
      "username": {
        ".write": "!data.exists() && newData.exists()",
      }
    }
  },
  "usernames": {
    "$username": {
      ".write": "!data.exists() && newData.exists()",
    }
  }

生成的 JSON:

{
  "usernames" : {
    "puf" : "DBP4Pw3uiwQfUaDJw1XBR8oFBUK2"
  },
  "users" : {
    "DBP4Pw3uiwQfUaDJw1XBR8oFBUK2" : {
      "username" : "puf"
    }
  }
}

最新更新