【问题标题】:Firebase android : make username uniqueFirebase android:使用户名唯一
【发布时间】:2016-05-16 13:43:37
【问题描述】:

Parse 将在今年年底关闭,因此我决定开始使用 Firebase。我需要实现一个包含 3 个字段的注册过程:电子邮件、用户名、密码(电子邮件和用户名对于我的应用程序必须是唯一的)。

由于 Firebase 没有提供像 Parse 这样管理用户名的简单方法,因此我决定仅使用电子邮件/密码注册并保存一些额外的数据,例如用户名。这是我的用户数据结构:

app : {
    users: {
       "some-user-uid": {
            email: "test@test.com"
            username: "myname"
       }
    }
}

但是,我想做的是使用户名唯一并在创建帐户之前对其进行检查。 这些是我的规则:

{
    "rules": {
        ".read": true,
        ".write": true,
        "users": {
            "$uid": {
                ".write": "auth !== null && auth.uid === $uid",
                ".read": "auth !== null && auth.provider === 'password'",
                "username": {".validate": "!root.child('users').child(newData.child('username').val()).exists()"}
            }
        }
   }
}

非常感谢您的帮助

【问题讨论】:

标签: android firebase firebase-security firebase-authentication


【解决方案1】:

为用户名创建一个新分支,当新用户登录时获取所有用户名的列表并检查它是否存在于 db 中,如果存在则显示它们,否则将其用户名放在用户名分支中..

【讨论】:

    【解决方案2】:

    按照 Frank 的建议保存用户名,但是当您保存用户名时,请使用 Firebase 中的 runTransaction 函数来确保不使用用户名。 Firebase 保证此函数是原子操作,因此您可以放心没有冲突

    firebaseRef.child("usernames").child(username).runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(MutableData mutableData) {
            if (mutableData.getValue() == null) {
                mutableData.setValue(authData.getUid());
                return Transaction.success(mutableData);
            }
    
            return Transaction.abort();
        }
    
        @Override
        public void onComplete(FirebaseError firebaseError, boolean commited, DataSnapshot dataSnapshot) {
            if (commited) {
                // username saved
            } else {
                // username exists
            }
        }
    });
    

    【讨论】:

    • 您在用户名列表中设置了它,但在 uid 中没有。我们是否应该在完成时添加一行来做到这一点?
    【解决方案3】:

    我还不太了解 firebase 安全性,但我可能已经使用 Java 解决了这个问题。我已经在下面发布了。

    我的数据结构是

    myapp
    {
      users: {
              <unique generated-id>
              { username: "example.username" }
    }
    }
    
    
    public boolean isUsernameExists(final String enteredUsername) {
            final Boolean[] isExist = {false};
            FBref.child("users").addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
                        String existingUsername = (String) userSnapshot.child("userName").getValue();
                        if (existingUsername.equals(enteredUsername)) {
                            isExist[0] = true;
                        }
                    }
                }
                @Override
                public void onCancelled(FirebaseError firebaseError) {
                    //some error thrown here
                }
            });
            return isExist[0];
        }
    

    【讨论】:

      【解决方案4】:

      部分答案是存储用户名索引,您可以在安全规则中对其进行检查:

      app : {
          users: {
             "some-user-uid": {
                  email: "test@test.com"
                  username: "myname"
             }
          },
          usernames: {
              "myname": "some-user-uid"
          }
      }
      

      所以usernames 节点将用户名映射到 uid。它基本上读作“用户名'myname'归'some-user-uid'所有”。

      使用此数据结构,您的安全规则可以检查给定用户名是否已经存在条目:

      "users": {
        "$uid": {
          ".write": "auth !== null && auth.uid === $uid",
          ".read": "auth !== null && auth.provider === 'password'",
          "username": {
            ".validate": "
              !root.child('usernames').child(newData.val()).exists() ||
              root.child('usernames').child(newData.val()).val() == $uid"
          }
        }
      }
      

      这验证用户名尚未被任何人认领或被当前用户认领。

      【讨论】:

      • 很好的答案,与stackoverflow.com/questions/25294478/…重复
      • 嗨,弗兰克,我认为还需要注意的是,您可能应该将所有对 usernames 的检查转换为小写并存储小写,这样您就不能拥有不同大小写的相同用户名。 users/some-user-uid/username 字段中存储的值可以区分大小写,可以是可读版本,这应该允许更友好的用户名选择和大小写。
      • @Frank van Puffelen 你能确认 Viv 在他关于使用 Transection 而不是普通集合查询的回答中所说的话吗?此外,您之前编写的任何正则表达式都可用于验证用户名的允许字符吗?
      • 感谢您的精彩回答!它真的帮助了我。但是我猜仍然存在一个问题。在您当前的实现中,同一个用户可以根据需要声明尽可能多的用户名(如果他们没有被占用)。所以他基本上可以创建username1直到usernameN。我们怎样才能实现,在他声称新用户名之前删除旧用户名?
      • 有一个倒转数据结构,将uid 映射到username,然后验证uid -> username === username -> uid
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-10
      • 2017-10-13
      • 2017-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多