【问题标题】:Firebase Database Rules for Unique Usernames唯一用户名的 Firebase 数据库规则
【发布时间】:2016-08-19 20:05:42
【问题描述】:

我正在尝试创建一个使用 Firebase 数据库来存储用户信息的网站。我想使用唯一的用户名。我有两个索引,一个用于用户,另一个用于用户名。

我的数据库结构如下:

users {
  $uid {
    username: "username1",
    gender: "xyz"
    email: "xyz"
  }
},
usernames {
    "username1": $uid"
}

用户使用他们的 $uid 声明用户名。

这些是我的规则:

{
  "rules": {
    "users": {
      "$uid": {
        ".write": "auth !== null && auth.uid === $uid",
        ".read": "auth !== null && auth.uid === $uid",
        "username": {
          ".validate": "
            !root.child('usernames').child(newData.val()).exists() ||
            root.child('usernames').child(newData.val()).val() == $uid"
        }
      }
    },
    "usernames" : {
      ".write": "!data.exists() && auth!= null",
      ".validate": "newData.val() == auth.uid"  <---- I can't get this too work
    }
  }
}

在 $uid 下设置用户名时,它会检查用户名索引,因此用户名只能使用未使用的用户名或具有自己的 $uid 的用户名写入。

我只想要值是经过身份验证的用户 uid 并且键是用户名的数据。我不能让这个工作。我怀疑我使用 newData().val() 不正确。我的验证语句失败。

我想避免使用自定义令牌,但我愿意接受任何建议。提前致谢。

对不起,如果这个解释过于冗长,这是我在 StackOverflow 上的第二篇文章。

编辑 #2 我做了一些研究,据我所知,我在文档中找到的所有内容都谈到了在 .val() 之前使用 .child() 的必要性,但我需要 .child 来获取变量而不是设置的用户名。

【问题讨论】:

  • 你说你不能让它工作,但你没有说它怎么不工作。无论值如何,它都会失败还是通过验证?
  • 我支持carant:乍一看,规则看起来不错。什么失败了?对于这样的事情,它有助于查看当前的 JSON(作为文本,没有屏幕截图)和失败的写入操作。
  • 很抱歉不够清晰。我目前无法验证用户名。

标签: firebase firebase-realtime-database firebase-security


【解决方案1】:

对不起,如果我迟到了,但我遇到了类似的问题,我将用户名规则更改为以下内容:

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

【讨论】:

    【解决方案2】:

    一旦您想允许人们更改用户名,接受的答案就会引起问题。

    通过稍微改变您的数据库结构,您可以轻松地在 firebase 中管理用户名。您还可以允许用户更改他们的用户名。

    数据库:

    usernames: {
      username1: {
        owner: "userId1"
      },
      username2: {
        owner: "userId2"
      },
      ...
    }
    

    以下规则将:

    • 阻止任何用户更改/删除其他用户的用户名
    • 让新用户创建用户名
    • 让用户通过删除旧用户名并创建新用户名来更改用户名

    (为了可读性而在换行符处拆分)

        "usernames": {
          "$username": {
            ".read": "true",
            ".write": "auth != null &&
              (
                \\ Allow user to delete only their own username
                (data.exists() && data.child('owner').val() === auth.uid && !newData.child('owner').exists())
                || 
                \\ Allow user to create a new username if the username is not taken
                (!data.exists() && newData.child('owner').val() === auth.uid)
              )"
          }
      }
    

    此更新将创建一个用户:

      const toAdd = {}
      toAdd[`usernames/${username}`] = { owner: userId };
      firebase.database().ref().set(toAdd)
    

    此更新将更改用户用户名:

    const update = {}
    update[`usernames/${previousUsername.toLowerCase()}`] = null;
    update[`usernames/${newUsername.toLowerCase()}`] = { owner: userId };
    firebase.database().ref().update(update)
    

    在您的代码中,您还应该在发送更新之前查询数据库以检查用户名是否存在。

    为什么我避免使用username: userId 方法:

    你说

    编辑#2 我做了一些研究,据我所知,我在文档中找到的所有内容都谈到了在 .val() 之前使用 .child() 的必要性,但我需要 .child 来获取变量而不是集合用户名。

    我相信这是正确的。对于您的用户名设置:

    usernames {
        "username1": userId1,
        "username2": userId2,
        ...
    }
    

    This answer描述了一种在请求中发送关键信息的方法:

    ref.update({
    _username: "username3",
    username3: "userId3",
    })
    

    然后你可以用类似这样的规则检查用户名是否在数据库中

    data.child(newData.child('_username').val()).exists()
    

    但是,在您的用户名设置中,您将使用此更新覆盖其他用户名。为避免这种情况,您需要在用户名路径usernames/username3 = userId3 处设置新数据。但是你不能像这样设置它,因为你又回到了没有在规则中引用的关键的问题。

    您需要创建一个无意义的结构,例如:

    usernames: {
      username1: {
        _username: "username1",
        userId: "userId1"
      }  
    }
    

    所以我选择了更简单,但不幸的是,我在开始时描述的用户名数据库设置不太美观。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-29
      • 2017-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多