Firestore规则 - 仅返回的列表集合
我知道这个问题的答案是:Firebase规则不是过滤系统! 但是我已经(对于带房间的聊天应用程序),我对安全性有问题。
房间集合
- ...有关房间的信息...
- 参与者:[ID1,ID2,ID3]
- 消息子汇编
当用户打开房间视图时,他只能看到房间当他的ID在“参与者”阵列中时。 我可以通过查询执行它,并且所有工作都很好,但是...
有没有办法拒绝所有集合上的列表操作以避免用户可以看到所有用户的所有房间?我知道我可以使用函数来限制访问权限,但是我想知道是否有一些方法可以使用Firestore规则进行操作。
我的安全规则:
prule_version ='2'; 服务cloud.firestore { match/databases/{database}/documents {
function authed() {
return request.auth.token.firebase.sign_in_provider == 'password' && request.auth != null && request.auth.token != null && request.auth.token.email != null;
}
function dataExists() {
return resource != null && resource.data != null;
}
function isConversationVisible() {
return dataExists() && resource.data.visible == true
}
function userInConversation() {
let email = request.auth.token.email;
return dataExists() && email in resource.data.participants;
}
function userInConversationUsingGet(convId) {
let email = request.auth.token.email;
let conv = get(/databases/$(database)/documents/conversations/$(convId));
return email in conv.data.participants;
}
match /conversations/{convId} {
allow create, delete, update: if false;
allow list, get: if authed() && isConversationVisible() && userInConversation();
match /messages/{messageId} {
allow create, read, list: if userInConversationUsingGet(convId);
allow delete, update: if false;
}
}
} }
和我的Java代码对其进行测试:
NOT WORKS
sChatQuery = sChatCollection
.whereArrayContains("participants", "[email protected]")
.whereEqualTo("type", type)
.whereEqualTo("visible", true)
.orderBy("timestamp", Query.Direction.DESCENDING);
NOT WORKS
FirebaseFirestore.getInstance()
.collection("conversations")
.get(Source.SERVER)
两个摘要都返回许可证。
我的Firestore的一个例子:
conversations
-- 61a8ec6c99791eb2f7ab5c69
---- participants ["[email protected]", "[email protected]", "[email protected]"]
-- 61a8ec6c99777sjskny77ahw
---- participants ["[email protected]", "[email protected]"]
-- 61a8ec6c9977718881666618
---- participants ["[email protected]"]
更新 我想查询失败是因为“
I know that the answer to this question is: Firebase rules is not a filter system!
But I've this case (for a chat app with rooms) and I've a problem with security.
Rooms collection
- ...info about room...
- participants: [id1, id2, id3]
- Messages subcollections
When the user open his rooms view, he should see only the rooms when his id is within "participants" array.
I can perform it with a query, and all works fine, but ...
Is there a way to deny the list operation on all collection to avoid that user could see all rooms of all users? I know that I can use a function to restrict the access, but I'm wondering if there are some ways to do it with firestore rules.
My security rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function authed() {
return request.auth.token.firebase.sign_in_provider == 'password' && request.auth != null && request.auth.token != null && request.auth.token.email != null;
}
function dataExists() {
return resource != null && resource.data != null;
}
function isConversationVisible() {
return dataExists() && resource.data.visible == true
}
function userInConversation() {
let email = request.auth.token.email;
return dataExists() && email in resource.data.participants;
}
function userInConversationUsingGet(convId) {
let email = request.auth.token.email;
let conv = get(/databases/$(database)/documents/conversations/$(convId));
return email in conv.data.participants;
}
match /conversations/{convId} {
allow create, delete, update: if false;
allow list, get: if authed() && isConversationVisible() && userInConversation();
match /messages/{messageId} {
allow create, read, list: if userInConversationUsingGet(convId);
allow delete, update: if false;
}
}
}
}
And my java code to test it:
NOT WORKS
sChatQuery = sChatCollection
.whereArrayContains("participants", "[email protected]")
.whereEqualTo("type", type)
.whereEqualTo("visible", true)
.orderBy("timestamp", Query.Direction.DESCENDING);
NOT WORKS
FirebaseFirestore.getInstance()
.collection("conversations")
.get(Source.SERVER)
Both snippets returns PERMISSION_DENIED.
An example of my firestore:
conversations
-- 61a8ec6c99791eb2f7ab5c69
---- participants ["[email protected]", "[email protected]", "[email protected]"]
-- 61a8ec6c99777sjskny77ahw
---- participants ["[email protected]", "[email protected]"]
-- 61a8ec6c9977718881666618
---- participants ["[email protected]"]
UPDATE
I suppose that the query fails because "[email protected]" is not within all documents (reading official docs).
But I'm wondering, how can I deny that a user perform a query passing arbitrary email address?
I'm thinking a rule that evaluates the email value passed on whereArrayContains is equal to request.auth.token.email. But I don't found a way to retrieve the parameter passed on query from firestore rules.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确定我是否正确理解您,但是如果您要禁止任何列出所有集合的人,则可以删除
list
权限,并且只允许get
操作。有关此的更多信息,请参见允许granular操作。如果要允许用户获得限制列表,则需要在安全规则中编码查询中的状况。因此,您必须检查
request.auth.uid
是否存在于参与者
要请求的文档的数组中。注意:我本人尚未测试过这种特定方案,但是规则引擎通常能够静态地确定该代码要求其授权执行的数据。
更新
在您共享的代码中,您正在尝试阅读整个集合:
firebase的安全规则不会过滤数据,而仅确保代码仅要求授权其授权文档。因此,您必须在查询和中过滤,然后在规则中检查该条件。
I'm not sure if I understand you correctly, but if you want to disallow anyone listing all collection, you can take away the
list
permission and only allowget
operations. For more on this, see the Firebase documentation on allowing granular operations.If you want to allow a user to get a limit list, you'll need to encode the condition you have in your query in your security rules too. So you'd have to check whether the
request.auth.uid
is present in theparticipants
array of the documents being requested.Note: I haven't tested this specific scenario myself, but the rules engine is often surprisingly capable in statically determining that the code is requesting data that it is authorized to do.
Update
In the code you shared, you're trying to read the entire collection:
Firebase's security rules don't filter data, but instead merely ensure that the code is only requesting documents that it is authorized for. So you will have to filter in a query and then check for that condition in your rules too.