【发布时间】:2020-12-30 07:25:27
【问题描述】:
我有一个名为 myusers 的 firestore 集合,其中包含大约 200 个包含用户信息的文档,例如电子邮件、姓名等。文档 ID 是 firebase uid。
我设置了以下安全规则
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isRestaurant() {
return request.auth.uid == 'agivenuser' || request.auth.uid == 'anothergivenuser';
}
match /myusers/{user} {
allow read: if resource.data.userId == request.auth.uid || isRestaurant();
allow create: if request.auth.uid != null;
match /mytok/{doc}/{document=**} {
allow read: if request.auth.uid == user || isRestaurant();
allow create: if request.resource.data.userId == request.auth.uid;
}
}
}
现在我尝试使用不使 isRestaurant() 为 true 的用户登录,并且看起来该用户可以访问整个 myusers 集合。我认为resource.data.userId == request.auth.uid 基本上会让用户只看到他的 uid 与给定文档的 userId 字段匹配的文档。实际上,他可以看到整个集合以及其中的所有文档。
请注意,当我尝试使用 getDocuments() 读取集合时,我无法读取任何文档,但如果我创建一个流,看起来我可以读取所有内容。
这是我获取文档的代码(无法读取集合)
void check() async {
final QuerySnapshot result = await Firestore.instance.collection('myusers').getDocuments();
final List<DocumentSnapshot> documents = result.documents;
documents.forEach((element) {
print(element['email']);
});
这是带有 StreamBuilder 的代码(它让我打印集合中每个文档的所有电子邮件)
Stream myStream;
@override
void initState() {
super.initState();
myStream = _firestore.collection('myusers').snapshots();
}
SliverList(
delegate: SliverChildListDelegate([
StreamBuilder<QuerySnapshot>(
stream: myStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Text(
'Loading...',
style: kSendButtonTextStyle.copyWith(color: kColorText),
);
default:
customerDB = snapshot.data.documents;
snapshot.data.documents.forEach((element) {
print(element['email']);
});
return new ListView(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
children: customerDB.map((DocumentSnapshot document) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Card(
color: kColorPrimaryLight,
child: ListTile(
title: Text(
(document['userName'] ?? 'xxx'),
),
),
);
}).toList(),
);
}
},
)
]),
),
我做错了什么?
【问题讨论】:
-
"实际上任何用户都可以看到 entore 集合以及其中的所有文档。" - 您是如何得出这个结论的?你做了什么来证明这一点?请编辑问题以充分解释。
-
嗨,Doug,我添加了更多上下文。看起来,作为用户,我能够阅读整个集合,而不仅仅是集合中 userId = 到 uid 的文档
-
您的代码使用了一个名为“myuser”的集合,但您的规则说的是“myusers”。
-
错字已更正,谢谢
-
嗨,Doug,您看到我的代码中有任何错误吗?给定用户可以访问集合“myusers”中的所有文档,而我希望他只能访问他的文档(= 字段“userId”等于 uid 的那个)
标签: firebase google-cloud-firestore firebase-security