【发布时间】:2018-05-04 11:37:35
【问题描述】:
问题
我已经多次看到这个问题(也在 Firebase 实时数据库的背景下),但我还没有看到令人信服的答案。问题陈述相当简单:
(经过身份验证的)用户如何选择尚未使用的用户名?
首先,为什么:用户认证后,他们有一个唯一的用户 ID。然而,许多网络应用程序让用户选择“显示名称”(用户希望如何出现在网站上),以保护用户的个人数据(如真实姓名)。
用户集合
给定如下数据结构,可以为每个用户存储用户名和其他数据:
/users (collection)
/{uid} (document)
- name: "<the username>"
- foo: "<other data>"
但是,没有什么能阻止其他用户(使用不同的{uid})在他们的记录中存储相同的name。据我所知,没有“安全规则”可以让我们检查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;
}
我相信解决方案已经成功了一半。但是,仍有一些未解决的问题。
剩余问题/疑问
这个实现已经相当复杂了,但它甚至没有解决用户想要更改他们的用户名的问题(需要记录删除或更新规则等)
另一个问题是,没有什么能阻止用户在 usernames 集合中添加多条记录,从而有效地抢夺所有好的用户名来破坏系统。
所以问题:
- 是否有更简单的解决方案来强制使用唯一用户名?
- 如何防止向
usernames集合发送垃圾邮件? - 如何使用户名检查不区分大小写?
我还尝试强制存在 users,为 /usernames 集合使用另一个 exists() 规则,然后提交批量写入操作,但是,这似乎不起作用(“缺失或不足权限”错误)。
另一个注意事项:我已经看到了带有客户端检查的解决方案。 但这些都不安全。任何恶意客户端都可以修改代码,省略检查。
【问题讨论】:
-
有人在 Firestore twittert 上工作,我相信他建议没有必要创建反向查找:twitter.com/abeisgreat/status/920730970751254528
-
你有没有想出一个可靠的解决方案?
-
我基本上是在使用上面的解决方案,我实现了支持更新用户名的规则,但是恶意垃圾邮件和不区分大小写的匹配仍然是一个悬而未决的问题。
-
如何将客户端检查移至函数?让用户向函数发送“更改用户名请求”,并在那里进行检查。如果成功,则从应该是只读的函数中设置用户的用户名。
-
我很确定这是函数的主要用例之一。从设备上卸载密集的数据处理(例如缩略图生成),在安全的环境中执行敏感操作(例如强制使用唯一用户名)并发送推送通知/电子邮件(ofc。还有更多)。
标签: firebase google-cloud-firestore