问题
我已经多次看到这个问题(也在 Firebase 实时数据库的上下文中),但我还没有看到令人信服的答案。问题陈述相当简单:
How can (authenticated) users choose a username that hasn't been taken yet?
首先,原因:用户经过身份验证后,他们将拥有唯一的用户 ID。然而,许多网络应用程序让用户选择“显示名称”(用户希望在网站上显示的方式),以保护用户的个人数据(如真实姓名)。
用户集合
给定如下所示的数据结构,可以为每个用户存储用户名以及其他数据:
/users (collection)
/{uid} (document)
- name: "<the username>"
- foo: "<other data>"
但是,没有什么可以阻止其他用户(具有不同的 {uid}
)在其记录中存储相同的name
。据我所知,没有“安全规则”允许我们检查名称
是否已被其他用户使用。
注意:客户端检查是可能的,但不安全,因为恶意客户端可能会忽略检查。
反向映射
流行的解决方案是创建具有反向映射的集合:
/usernames (collection)
/{name} (document)
- uid: "<the auth {uid} field>"
鉴于此反向映射,可以编写安全规则来强制用户名尚未被占用:
match /users/{userId} {
allow read: if true;
allow create, update: if
request.auth.uid == userId &&
request.resource.data.name is string &&
request.resource.data.name.size() >= 3 &&
get(/PATH/usernames/$(request.resource.data.name)).data.uid == userId;
}
并强制用户首先创建用户名文档:
match /usernames/{name} {
allow read: if true;
allow create: if
request.resource.data.size() == 1 &&
request.resource.data.uid is string &&
request.resource.data.uid == request.auth.uid;
}
我相信解决方案已经成功了一半。然而,仍有一些 Unresolved 问题。
剩余问题
这个实现已经相当复杂,但它甚至没有解决用户想要更改用户名的问题(需要记录删除或更新规则等)
另一个问题是,没有什么可以阻止用户在 usernames
集合中添加多个记录,从而有效地抢夺所有好的用户名来破坏系统。
所以问题是:
- 是否有更简单的解决方案来强制使用唯一的用户名?
- 如何防止向
用户名
集合发送垃圾邮件? - 如何使用户名检查不区分大小写?
我还尝试强制 users
存在,并使用/usernames 集合的另一个 exists()
规则,然后提交批量写入操作,但是,这并没有似乎不起作用(“权限缺失或不足”错误)。
另一个注意事项:我已经看到了带有客户端检查的解决方案。 但是这些是不安全的。任何恶意客户端都可以修改代码并忽略检查。
最佳答案
Twitter 上的
@asciimike
是 Firebase 安全规则开发人员。
他说,目前还没有办法强制文档上的键的唯一性。 https://twitter.com/asciimike/status/937032291511025664
由于 firestore
基于 Google Cloud datastore
,因此它继承了此问题。自 2008 年以来,这是一个长期存在的要求。
https://issuetracker.google.com/issues/35875869#c14
但是,您可以通过使用 firebase 函数
和一些严格的安全规则
来实现您的目标。
您可以在 Medium 上查看我提出的整个解决方案。 https://medium.com/@jqualls/firebase-firestore-unique-constraints-d0673b7a4952
关于firebase - 云Firestore : Enforcing Unique User Names,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47405774/