Firebase android:使用户名唯一

时间:2016-02-06 16:37:48

标签: android firebase firebase-security firebase-authentication

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()"}
            }
        }
   }
}

非常感谢您的帮助

3 个答案:

答案 0 :(得分:46)

部分答案是存储您在安全规则中检查的用户名索引:

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

因此usernames节点将用户名映射到uid。它本质上读作“username'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"
    }
  }
}

这验证了当前用户尚未声明用户名或者当前用户声明的用户名。

答案 1 :(得分:4)

按照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
        }
    }
});

答案 2 :(得分:-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];
    }