Cloud Firestore:强制使用唯一用户名 [英] Cloud Firestore: Enforcing Unique User Names

查看:19
本文介绍了Cloud Firestore:强制使用唯一用户名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

我已经多次看到这个问题(也在 Firebase 实时数据库的上下文中),但我没有看到令人信服的答案.问题陈述相当简单:

I have seen this question several times (also in the context of the Firebase Real-Time Database), but I haven't seen a convincing answer to it. The problem statement is fairly simple:

(经过身份验证的)用户如何选择尚未被使用的用户名?

首先,为什么:用户通过身份验证后,他们有一个唯一的用户 ID.然而,许多网络应用程序让用户选择显示名称"(用户希望如何在网站上显示),以保护用户的个人数据(如真实姓名).

First of all, the why: After a user authenticates, they have a unique user ID. Many web-apps, however, let the user choose a "display name" (how the user wants to appear on the website), in order to protect the users personal data (like real name).

用户集合

给定如下数据结构,可以为每个用户存储用户名和其他数据:

Given a data structure like the following it is possible to store a username along with other data for each user:

/users  (collection)
    /{uid}  (document)
        - name: "<the username>"
        - foo: "<other data>"

然而,没有什么可以阻止另一个用户(具有不同的 {uid})在他们的记录中存储相同的 name.据我所知,没有安全规则"允许我们检查 name 是否已经被另一个用户使用.

However, nothing prevents another user (with a different {uid}) to store the same name in their record. As far as I know, there is no "security rule" that allows us to check if the name has already been by another user.

注意:客户端检查是可能的,但不安全,因为恶意客户端可能会忽略检查.

Note: A client side check is possible, but unsafe as a malicious client could omit the check.

反向映射

流行的解决方案是使用反向映射创建一个集合:

Popular solutions are creating a collection with a reverse mapping:

/usernames  (collection)
    /{name}  (document)
       - uid: "<the auth {uid} field>"

鉴于这种反向映射,可以编写安全规则来强制用户名未被占用:

Given this reverse mapping, it is possible to write a security rule to enforce that a username is not already taken:

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;
}

并强制用户首先创建用户名文档:

and to force a user to create a usernames document first:

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;
}

我相信解决方案已经完成了一半.但是,仍有一些未解决的问题.

I believe the solution is half-way there. However, there are still a few unsolved issues.

剩余问题/疑问

这个实现已经很复杂了,但它甚至没有解决用户想要更改用户名的问题(需要记录删除或更新规则等)

This implementation is quite involved already but it doesn't even solve the problem of users that want to change their user name (requires record deletion or update rules, etc.)

另一个问题是,没有什么可以阻止用户在 usernames 集合中添加多个记录,有效地抢夺所有好的用户名来破坏系统.

Another issue is, nothing prevents a user from adding multiple records in the usernames collection, effectively snatching all good usernames to sabotage the system.

对于问题:

  • 是否有更简单的解决方案来强制使用唯一的用户名?
  • 如何防止向 usernames 集合发送垃圾邮件?
  • 如何使用户名检查不区分大小写?

我还尝试强制存在 users,对/usernames 集合使用另一个 exists() 规则,然后提交批量写入操作,但是,这不会t 似乎有效(权限缺失或不足"错误).

I tried also enforcing existence of the users, with another exists() rule for the /usernames collection and then committing a batch write operation, however, this doesn't seem to work ("Missing or insufficient permissions" error).

另一个注意事项:我已经看到了客户端检查的解决方案.但这些都不安全.任何恶意客户端都可以修改代码,并省略检查.

Another note: I have seen solutions with client-side checks. BUT THESE ARE UNSAFE. Any malicious client can modify the code, and omit checks.

推荐答案

@asciimike 在 twitter 上是一个 firebase 安全规则开发者.他说目前没有办法强制文档上的键的唯一性.https://twitter.com/asciimike/status/937032291511025664

@asciimike on twitter is a firebase security rules developer. He says there is currently no way to enforce uniqueness on a key on a document. https://twitter.com/asciimike/status/937032291511025664

由于 firestore 基于 Google Cloud datastore 它继承了这个问题.自 2008 年以来,这是一个长期存在的要求.https://issuetracker.google.com/issues/35875869#c14

Since firestore is based on Google Cloud datastore it inherits this issue. It's been a long standing request since 2008. https://issuetracker.google.com/issues/35875869#c14

但是,您可以通过使用 firebase 函数 和一些严格的安全规则来实现您的目标.

However, you can achieve your goal by using firebase functions and some strict security rules.

您可以在媒体上查看我提出的整个解决方案.https://medium.com/@jqualls/firebase-firestore-unique-constraints-d0673b7a4952

You can view my entire proposed solution on medium. https://medium.com/@jqualls/firebase-firestore-unique-constraints-d0673b7a4952

这篇关于Cloud Firestore:强制使用唯一用户名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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