问题
我已多次看到这个问题(也在Firebase实时数据库的上下文中),但我还没有看到令人信服的答案.问题陈述相当简单:
(经过身份验证的)用户如何选择尚未使用的用户名?
首先,原因是:用户进行身份验证后,他们拥有唯一的用户ID.然而,许多网络应用程序允许用户选择"显示名称"(用户希望如何在网站上显示),以保护用户的个人数据(如真实姓名).
用户集合
给定如下的数据结构,可以为每个用户存储用户名和其他数据:
/users (collection)
/{uid} (document)
- name: "<the username>"
- foo: "<other data>"
Run Code Online (Sandbox Code Playgroud)
但是,没有什么能阻止另一个用户(具有不同的用户{uid})将其存储name在他们的记录中.据我所知,没有"安全规则"允许我们检查name其他用户是否已经访问过.
注意:可以进行客户端检查,但作为恶意客户端的不安全可能会忽略检查.
反向映射
流行的解决方案是创建一个带有反向映射的集合:
/usernames (collection)
/{name} (document)
- uid: "<the auth {uid} field>"
Run Code Online (Sandbox Code Playgroud)
鉴于此反向映射,可以编写安全规则以强制尚未使用用户名:
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;
}
Run Code Online (Sandbox Code Playgroud)
并强制用户首先创建用户名文档:
match /usernames/{name} {
allow read: if true;
allow create: if
request.resource.data.size() …Run Code Online (Sandbox Code Playgroud) 在Firestore中是否可以定义具有唯一约束的索引?如果没有,如何在文档字段上强制唯一性(不使用文档ID)?
我的数据库(firestore)中有以下字符集合结构
/characters/{uid}
- username: string
- clan: string
- mana: number
- health: number
etc...
Run Code Online (Sandbox Code Playgroud)
我正在尝试/characters/{uid}通过以下逻辑找出安全规则
service cloud.firestore {
match /databases/{database}/documents {
// Characters
match /characters/{characterID} {
allow create: if isValidUsername();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里的函数isValidUsername检查各种内容,如长度、特殊字符等......但我无法弄清楚的一件事是如何检查函数内部
确保它request.resource.data.username是唯一的,即不存在于任何其他/characters收藏文档中。
firebase google-cloud-datastore angularfire2 angular google-cloud-firestore