Ent*_*eco 5 android firebase firebase-security google-cloud-firestore
考虑这个简单的 Firestore 数据库结构:
1:Firestore结构
cities/
city1/
name:Beijing
likes: 0
dislikes: 0
... more fields
city2/
name: New York
likes: 21
dislikes: 1
... more fields
Run Code Online (Sandbox Code Playgroud)
为了保护数据库免受意外操作,我添加了以下 Firestore 安全规则
2 Firestore 安全规则:
// Allow read/write access to all users under any conditions
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{cityId} {
allow read: if request.auth.uid != null;
allow update: if request.auth.uid != null &&
request.resource.data.keys().hasOnly(["likes", "dislikes"]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这基本上允许我执行这些要求:
问题
为什么Exception: PERMISSION_DENIED: Missing or insufficient permissions.当我尝试使用批量写入时,上面的设置给了我一个, 但如果我单独写入更改则成功?
例如,下面的代码(使用批量写入)失败:PERMISSION_DENIED:权限缺失或不足。
fun rate(likes: List<String>, dislikes: List<String>, done: (Boolean) -> Unit) {
db.runBatch { batch ->
likes.map { cityCollection.document(it) }.forEach { doc ->
batch.update(doc,"likes", FieldValue.increment(1))
}
dislikes.map { cityCollection.document(it) }.forEach { doc ->
batch.update(doc,"dislikes", FieldValue.increment(1))
}
}.addOnCompleteListener { task ->
task.exception() // Exception: PERMISSION_DENIED: Missing or insufficient permissions.
done(task.isSuccessful) // false
}
}
Run Code Online (Sandbox Code Playgroud)
如果没有 Batching,代码就可以正常工作。例如,这完美地工作:
override fun rate(likes: List<String>, dislikes: List<String>, done: (Boolean) -> Unit) {
val tasks = likes.map { cityCollection.document(it) }.map { doc ->
doc.update("likes", FieldValue.increment(1))
}.union(dislikes.map { cityCollection.document(it) }.map { doc ->
doc.update("dislikes", FieldValue.increment(1))
})
Tasks.whenAllComplete(tasks).addOnCompleteListener { task ->
done(task.isSuccessful) // true
}
}
Run Code Online (Sandbox Code Playgroud)
关于我的安全规则,我需要了解批量写入/事务有什么特别之处吗?我希望这些更新以原子方式执行,因此我最初尝试使用批量写入。但是,我似乎无法让它们与我的安全规则结合使用。
您应该知道它request.resource.data.keys()包含现有文档中的所有键,而不仅仅是正在更新的键。 request.resource.data代表文档的最终状态(如果您允许写入完成)。因此,如果您要更新已包含其他字段的文档,您的规则将始终拒绝访问,并hasOnly返回 false。
由于在这两种情况下您都没有显示现有文档的内容,因此实际上不可能确切地说出这在哪里使您的代码出错。但这几乎肯定就是这里发生的事情。更新是否来自单个文档写入、批量更新或事务都无关紧要。它们都受到相同规则的限制。
(您过去可以使用名为 writeFields 的属性来仅查找正在更新的字段,但该属性已被弃用 - 不要使用它。)
如果您想执行每个字段的限制,它实际上比您现在编写的内容要复杂得多。您必须检查(且仅当)特定字段是否已被修改,同时还要检查是否没有其他字段被更改。请参阅此问题了解更多详细信息:
Cloud Firestore 安全规则 - 只允许写入文档中的特定密钥
| 归档时间: |
|
| 查看次数: |
905 次 |
| 最近记录: |