如何防止 Firebase 中的重复用户属性? [英] How do you prevent duplicate user properties in Firebase?

查看:25
本文介绍了如何防止 Firebase 中的重复用户属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 FirebaseSimpleLogin 创建用户并处理身份验证.

I'm Using FirebaseSimpleLogin to create users and handle authentication.

当我尝试通过 $createUser() 方法通过简单登录创建新用户时,如果电子邮件地址已被使用,firebase 将不会创建用户.但是,我还使用 $set() 将我创建的用户保存到我的 firebase 中,并且我使用 user.uid 作为键.尝试写入数据库时​​,即使用户名不是唯一的,firebase 也会保存记录,因为简单登录只需要电子邮件和密码.那么,当用户名未被用作用户对象的密钥时,如何验证该用户名是唯一的?

When I try and create a new user with simple login via the $createUser() method, firebase won't create the user if the email address has already been used. However, I am also using $set() to save my created users to my firebase after I create them and I am using user.uid as the key. When trying to write to the database, firebase will save the record even if the username is not unique since only email and password are required for simple login. So how can I validate a username to be unique when it is not being used as the key to the user object?

我正在创建这样的新用户:

I'm creating new users like this:

$scope.createUser = function() {
  $scope.auth.$createUser('trinker@gmail.com', 'password').then(function(user, err) {
    if (!err) {
      ref.child('users/' + user.uid).set({
        email: user.email,
        username: user.username
      });
      console.log("success!");
    }else{
      console.log(err.message);
    }
  });
}

我的用户对象如下所示:

And my user object looks like this:

{
  "users" : {
    "simplelogin:28" : {
      "email" : "trinker@gmail.com",
      "username" : "jtrinker"
    },
    "simplelogin:30" : {
      "email" : "test@gmail.com",
      "username" : "jtrinker"
    }
  }
}

}

我需要使用 uid 作为每个用户的密钥,但我仍然需要用户名是唯一的.

I need to use the uid as the key for each user, but I still need the username to be unique.

如果一个对象中的属性对于另一个对象中的属性不是唯一的,我如何防止 Firebase 保存记录?

How can I can I prevent firebase from saving records if properties within one object are not unique to properties inside a different object?

推荐答案

首先,如果用户已经有一个username,它是唯一的,这不会消失,我会建议您放弃使用简单的登录uids.正如您在此处已经发现的那样,这只会产生试图在两者之间来回切换的问题.使用创建您自己的令牌href="https://github.com/Rigidflame/firebase-passport-login" rel="noreferrer">firebase-passport-login 然后按用户名存储记录.

First of all, if users already have a username, it's unique, and this is not going to go away, I'd recommend that you give up on using simple login uids. This is going to create nothing but issues trying to flip back and forth between the two, as you've already discovered here. Investigate creating your own tokens with a tool like firebase-passport-login and then store the records by username.

但既然这不是你的问题,那么让我们在我们在这里的时候解决这个问题,因为你可能想继续进入我多次穿越的双重身份的荆棘丛中.

But since that wasn't your question, let's resolve that while we're here, since you may want to go ahead and enter the thorny briar of dual identities through which I have passed many times.

要使用户名唯一,请存储用户名索引.

To make the username unique, store an index of usernames.

/users/$userid/username/$username
/usernames/$username/$userid

为确保它们的唯一性,请在 usernames/path 中的用户 ID 上添加如下安全规则,以确保每个用户名只能分配一个用户,并且值为用户的 ID:

To ensure they are unique, add a security rule as follows on the user id in usernames/ path, which ensures only one user can be assigned per username and that the value is the user's id:

".write": "newData.val() === auth.uid && !data.exists()"

现在通过将以下内容添加到用户/记录中的用户名来强制它们匹配:

Now enforce that they match by adding the following to the username in the users/ record:

"users": {
   "$userid": {
      "username": {
         ".validate": "root.child('usernames/'+newData.val()).val() === $userid"
      }
   }
}

这将确保 ID 是唯一的.小心阅读权限.您可能希望完全避免这些,因为您不希望任何人查找私人电子邮件或用户名.像我在支持中展示的那样保存这些是理想的.

This will ensure the ids are unique. Be careful with read privileges. You may want to avoid those entirely since you don't want anyone looking up private emails or usernames. Something like I demonstrated in support for saving these would be ideal.

这里的想法是您尝试分配用户名和电子邮件,如果它们失败,则它们已经存在并属于另一个用户.否则,您将它们插入到用户记录中,现在用户可以通过 uid 和电子邮件进行索引.

The idea here is that you try to assign the username and email, if they fail, then they already exist and belong to another user. Otherwise, you insert them into the user record and now have users indexed by uid and email.

为了遵守 SO 协议,这里是该要点中的代码,最好通过链接阅读:

To comply with SO protocol, here's the code from that gist, which is better read via the link:

var fb = new Firebase(URL);

function escapeEmail(email) {
   return email.replace('.', ',');
}

function claimEmail(userId, email, next) {
   fb.child('email_lookup').child(escapeEmail(email)).set(userId, function(err) {
      if( err ) { throw new Error('email already taken'); }
      next();
   });
}

function claimUsername(userId, username, next) {
   fb.child('username_lookup').child(username).set(userId, function(err) {
      if( err ) { throw new Error('username already taken'); }
      next();
   });   
}

function createUser(userId, data) {
   claimEmail(userId, data.email, claimUsername.bind(null, userId, data.username, function() {
      fb.child('users').child(userId).set(data);
   );   
}

和规则:

{
  "rules": {
     "users": {
        "$user": {
           "username": {
               ".validate": "root.child('username_lookup/'+newData.val()).val() === auth.uid"
           },
           "email": {
               ".validate": "root.child('email_lookup').child(newData.val().replace('.', ',')).val() === auth.uid"
           }
        }
     },

     "email_lookup": {
        "$email": {
           // not readable, cannot get a list of emails!
           // can only write if this email is not already in the db
           ".write": "!data.exists()",
           // can only write my own uid into this index
           ".validate": "newData.val() === auth.uid"
        }
     },
     "username_lookup": {
        "$username": {
           // not readable, cannot get a list of usernames!
           // can only write if this username is not already in the db
           ".write": "!data.exists()",

           // can only write my own uid into this index
           ".validate": "newData.val() === auth.uid"
        }
     },
  }
}

这篇关于如何防止 Firebase 中的重复用户属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆