Firebase android : 使用户名唯一
Firebase android : make username unique
Parse 将在年底关闭,所以我决定开始使用 Firebase。我需要实现一个包含 3 个字段的注册过程:电子邮件、用户名、密码(电子邮件和用户名 对我的应用来说必须是唯一的)。
因为 Firebase 没有提供像 Parse 这样管理用户名的简单方法,我决定只使用 email/password 注册并保存一些额外的数据,比如用户名。这是我的用户数据结构:
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()"}
}
}
}
}
非常感谢您的帮助
部分答案是存储用户名索引,您可以在安全规则中对其进行检查:
app : {
users: {
"some-user-uid": {
email: "test@test.com"
username: "myname"
}
},
usernames: {
"myname": "some-user-uid"
}
}
因此 usernames
节点将用户名映射到 uid。它基本上读作 "username 'myname' is owned by '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"
}
}
}
这验证用户名尚未被任何人声明或当前用户已声明。
我还不太了解 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];
}
按照 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
}
}
});
为用户名创建一个新分支,当新用户登录时获取所有用户名的列表,并检查它是否存在于数据库中,如果存在则向他们展示敬酒,否则将其用户名放入用户名分支..
Parse 将在年底关闭,所以我决定开始使用 Firebase。我需要实现一个包含 3 个字段的注册过程:电子邮件、用户名、密码(电子邮件和用户名 对我的应用来说必须是唯一的)。
因为 Firebase 没有提供像 Parse 这样管理用户名的简单方法,我决定只使用 email/password 注册并保存一些额外的数据,比如用户名。这是我的用户数据结构:
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()"}
}
}
}
}
非常感谢您的帮助
部分答案是存储用户名索引,您可以在安全规则中对其进行检查:
app : {
users: {
"some-user-uid": {
email: "test@test.com"
username: "myname"
}
},
usernames: {
"myname": "some-user-uid"
}
}
因此 usernames
节点将用户名映射到 uid。它基本上读作 "username 'myname' is owned by '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"
}
}
}
这验证用户名尚未被任何人声明或当前用户已声明。
我还不太了解 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];
}
按照 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
}
}
});
为用户名创建一个新分支,当新用户登录时获取所有用户名的列表,并检查它是否存在于数据库中,如果存在则向他们展示敬酒,否则将其用户名放入用户名分支..