firebase - 即使在查询结果中没有找到文档,Firebase 也会执行“读取”规则
问题描述
在我的 Firebase Firestore 规则中,我对“课程”集合有以下规则:
rules_version = '2'
service cloud.firestore {
match /databases/{database}/documents {
match /courses/{courseId} {
allow read: if resource.data.userId == request.auth.uid;
}
}
}
如果使用 firebase Web 客户端读取单个文档,则这些规则可以正常工作。但是当查询结果为空时,例如以下查询:
const results = await app.firestore().collection('courses')
.where('userId', '==', 'unexistingUserId').get();
然后规则失败,在客户端抛出异常(缺少权限或权限不足)。
在模拟器上本地运行时,我发现问题在于正在针对包含查询字段的资源验证读取规则,即使该资源不存在:
如上所示,resource.data.userId 包含“unexistingUserId”值。
为了解决这个问题,我不得不通过添加验证来检查资源是否存在来更改规则:
rules_version = '2'
service cloud.firestore {
match /databases/{database}/documents {
match /courses/{courseId} {
allow read: if resource==null || resource.data==null || !('id' in resource) || resource.data.userId == request.auth.uid;
}
}
}
现在,当查询没有结果时,规则验证正常,因为请求对象中不存在“id”:
所以我的问题是:
- 这是预期的行为吗?
- 如果查询没有返回任何内容,规则甚至不应该被验证吗?
- 有没有办法改变这种行为以避免在我的所有规则中添加这些检查?
解决方案
这是预期的行为吗?
如果查询没有返回任何内容,规则甚至不应该被验证吗?
这是预期的行为。您正在观察的是因为安全规则不是过滤器这一事实。请务必阅读并理解该链接文档。
查询的工作方式与单个文档 get() 不同。使用单个文档 get(),规则系统不必担心扩展以匹配数十亿个文档,因此检查一个文档的内容以查看其是否匹配是完全合理的。但是,由于查询可以返回 0 个或更多文档,因此对规则的考虑不同。他们不会简单地检查查询产生的每个文档。对于非常大的集合来说,这根本无法扩展。
规则通过检查客户端查询上的过滤器是否与规则中的约束匹配来处理查询。如果您这么说resource.data.userId == request.auth.uid
,您的意思是用户可能只尝试查询 userId 等于他们自己的 UID 的文档。他们甚至不允许尝试匹配查询中的任何其他文档。
唯一会通过此规则的查询看起来更像这样:
const results = await app.firestore()
.collection('courses')
.where('userId', '==', firebase.auth().currentUser)
.get();
在这种情况下,过滤器:
.where('userId', '==', firebase.auth().currentUser)
完全符合规则:
allow read: if resource.data.userId == request.auth.uid;
任何其他查询都将立即被拒绝,因为它试图访问已知违反规则的文档。
推荐阅读
- angular - 角度单元测试RouterLink错误TypeError:null不是对象(评估'this.urlSerializer.serializer')
- oracle11g - OBIEE 11g 代理 - 电子邮件分发列表 - 不工作
- amazon-sagemaker - 在 Amazon Sagemaker 中使用 Ground Truth 和 BlazingText 配置训练作业
- python - 渲染表单时如何不显示“Id:”?(与 'ParentClass ptr:' 相同)
- php - 如何使用 scopequery 执行高级搜索
- c# - 使用 ASP.NET C# 重写 HOST
- ios - 如何从 RAM 内存中清除图像
- c - 为什么我在env中添加的环境变量找不到
- html - 禁用的输入字段在 safari 中未正确呈现
- command-line-arguments - 错误:需要以下参数