在 Firestore 访问规则中使用
allow list;
和 allow read;
有什么区别?更具体地说,如果我只允许 list
而不是 read
津贴,我的数据会获得哪些额外保护?
在我看来,read 和 list 提供了相同的安全性,唯一的区别是
list
使得合法访问单个对象变得更加麻烦。毕竟,不良行为者可以简单地列出对象,然后读取其完整内容。如果他知道该对象的 ID,他可以简单地将其作为搜索项包含在内。
// The scopes collection is restricted to only allow 'list' requests.
// The scopes collection contains a 'postPhoto' document
// The following request will fail with an insufficient permission error, as expected
await db
.collection(`/auth/${client}/scopes`)
.doc('postPhoto')
.get()
.then(doc => console.log(doc.id, doc.data()))
.catch(e => console.error(e))
// But this request will succeed, and it is in effect the same as the previous
await db
.collection(`/auth/${client}/scopes`)
.where(firebase.firestore.FieldPath.documentId(), '==', 'postPhoto')
.get()
.then(col => col.forEach(doc => console.log(doc.id, doc.data())))
.catch(e => console.error(e))
我希望
list
访问权限只允许您查看文档的存在,但看不到它们的内容。但既然 list
显然也允许您访问底层文档数据,为什么不直接使用 read
呢?
实际上
list
是 read
的具体情况,如 文档中所述:
在某些情况下,将读取分解并将写入更多内容很有用 精细化操作。例如,...您可能希望允许单个文档读取但拒绝大型查询。
read规则可以分解为get和list
更具体地说,我们采用以下安全规则:
service cloud.firestore {
match /databases/{database}/documents {
match /col1/{docId=**} {
allow list: if request.auth.uid != null;
}
match /col2/{docId=**} {
allow get: if request.auth.uid != null;
}
}
}
以下查询将起作用:
firebase.firestore().collection("col1").get()
虽然这个不起作用:
firebase.firestore().collection("col2").get()
现在,让我们假设每个集合都有一个 id 为“1”的文档。
以下查询将起作用:
firebase.firestore().collection("col2").doc("1").get()
虽然这个不起作用:
firebase.firestore().collection("col1").doc("1").get()
最后,如果您按如下方式更改规则,使用
read
,以上所有查询都将起作用!
service cloud.firestore {
match /databases/{database}/documents {
match /col1/{docId=**} {
allow read: if request.auth.uid != null;
}
match /col2/{docId=**} {
allow read: if request.auth.uid != null;
}
}
}
来自 Firebase 文档:
规则可以分为read
和get
,而list
规则可以分为write
、create
和update
delete
write
规则定义非常清晰,get
和list
之间的区别如下:
- get 规则将单个文档的检索限制为公共文档或用户创作的文档。
- list 规则应用与 get 相同的限制,但适用于查询。它还检查查询限制,然后拒绝任何没有限制或限制大于 10 的查询。
(来自 安全查询数据 - Firebase 文档)
在编写规则时请注意,
read
分为 get
和 list
- 因此它可以做任何它们组合起来可以做的事情。
从你的问题来看,
在我看来,read 和 list 提供了相同的安全性,唯一的区别是 list 使得合法访问单个对象变得更加麻烦。
list
用于安全地查询集合,当您从客户端调用 collection()
方法时会被触发。 get
另一方面,当您调用从 doc()
方法接收数据时。
毕竟,不良行为者可以简单地列出对象,然后读取其完整内容。如果他知道该对象的 ID,他可以简单地将其作为搜索项包含在内。
是的,但另一方面,
get
可用于防止集合列表查询。 Firebase 团队使用 list 和 get 的更好原因似乎是为了更轻松地编写查询,而不是改变安全功能的方式。 (到目前为止,没有办法限制基于 where 子句的查询,否则它可以在您的场景中用于保护。)
通常,您永远不会同时使用
read
和 list
,因为 read
始终会覆盖 list
和 get
。
什么是
get
?
阅读您已经拥有文档 ID 的单个文档。
userCollection.doc(uid).snapshots()
什么是
list
?
使用
where
查询多个文档
userCollection.where('email', isEqualTo: email).snapshots()
什么时候使用
list
而不是read
?
我想让客户端获取他们已经知道的用户的详细信息
uid
就像当他们是聊天组的一部分并且他们想要查看每个参与者的详细信息但不希望客户端运行查询时获取许多用户文档。
我会用这样的东西
allow get : if isAuthenticated();
allow list : if false;