如何防止Firebase中的重复用户属性?
我正在使用FirebaseSimpleLogin
来创build用户并处理身份validation。
当我通过$createUser()
方法尝试创build一个简单login的新用户时,如果电子邮件地址已被使用,则firebase将不会创build该用户。 不过,我也使用$set()
将我创build的用户保存到我的user.uid
,然后创build它们,并使用user.uid
作为键。 当试图写入数据库时,即使用户名不唯一,firebase也会保存logging,因为只需简单login就可以使用电子邮件和密码。 那么我怎样才能validation一个用户名是唯一的,当它不被用作用户对象的关键?
我正在创build像这样的新用户:
$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); } }); }
而我的用户对象如下所示:
{ "users" : { "simplelogin:28" : { "email" : "trinker@gmail.com", "username" : "jtrinker" }, "simplelogin:30" : { "email" : "test@gmail.com", "username" : "jtrinker" } } } }
我需要使用uid作为每个用户的密钥,但我仍然需要用户名是唯一的。
如何防止firebase保存logging如果一个对象内的属性不是唯一的不同对象内的属性?
首先,如果用户已经有一个username
,它是唯一的,这是不会消失的,我build议你放弃使用简单的login用户名。 这不会造成任何问题,只是试图在两者之间来回翻转,正如你在这里已经发现的那样。 使用firebase-passport-login等工具调查创build自己的令牌 ,然后通过username
存储logging。
但既然这不是你的问题,让我们来解决,当我们在这里的时候,因为你可能想要继续前进,并进入我经历了许多次的双重身份的棘手的石楠。
要使用户名唯一,请存储用户名索引。
/ users / $ userid / username / $ username / usernames / $ username / $ userid
为了确保它们是唯一的,请在用户名/path中的用户标识中添加以下安全规则,以确保每个用户名只能分配一个用户,并且该值是用户的标识:
".write": "newData.val() === auth.uid && !data.exists()"
现在通过将以下内容添加到用户/logging中的用户名来强制匹配:
"users": { "$userid": { "username": { ".validate": "root.child('usernames/'+newData.val()).val() === $userid" } } }
这将确保ID是唯一的。 阅读权限要小心。 你可能想完全避免这些,因为你不想让任何人查看私人邮件或用户名。 像我表示支持保存这些东西将是理想的。
这里的想法是,你试图分配用户名和电子邮件,如果他们失败,那么他们已经存在,属于另一个用户。 否则,您将它们插入到用户logging中,并且现在已经通过uid和电子邮件索引了用户。
为了遵守SO协议,下面是来自该要点的代码,可以通过链接更好地阅读:
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" } }, } }
只是使用安全规则来检查它的存在不是更容易吗? 我有我的build立如下:
"usernames": { "$usernameid": { ".read": "auth != null", ".write": "auth != null && (!data.exists() || !newData.exists())" } }
这允许写入,如果用户名不存在。 我相信我直接从Firebase文档中获得了此信息。