我正在尝试使用新的 Firebase 跨服务安全规则 ( https://firebase.blog/posts/2022/09/announcing-cross-service-security-rules ),但存储规则访问 Firestore 数据时遇到一些问题。
问题似乎出在 userIsCreator() 函数
match /certification/{certificationId}/{fileId} {
function userIsCreator() {
let certification = firestore.get(/databases/(default)/documents/certifications/$(certificationId));
return firestore.get(certification.data.creatorRef).id == request.auth.uid;
}
allow read, write: if userIsCreator()
}
Firestore文档的内容是:
{
"data": {
othersValues,
"creatorRef": "/databases/%28default%29/documents/users/CuutSAtFkDX2F9T8hlT4pjMUByS2"
}
"id": "3EhQakDrsKxlacUjdibs"
"__name__":
"/databases/%28default%29/documents/certifications/3EhQakDrsKxlacUjdibs"
}
creatorRef 变量是用户对 Firestore 文档的引用。在 Users 集合中,文档 ID 是用户的 UID,因此我获取项目的 CreatorRef,然后检查引用的用户集合的 ID 是否与用户登录的 UID 相同。
同样的功能适用于 Firestore 规则,以避免更新认证文档(如果不是创建者),没有任何问题。
获取firestore.get后调用creatorRef似乎有问题,但没有意义!
已测试:
如果我使用 Firestore 存储规则验证器,它不会失败,并且表示我可以通过测试器中输入的 UID 访问该资源(对于其他 UID 则按预期失败)。但在我的应用程序中,即使使用创建者用户登录也会出现权限错误。
如果将函数更改为仅一次直接调用用户集合 id (
return firestore.get(/databases/(default)/documents/users/CuutSAtFkDX2F9T8hlT4pjMUByS2).id == request.auth。 uid;
),它正在测试器和我的应用程序中工作。但这不是一个解决方案,因为我需要首先获取创建者的 Users 集合引用!
对于测试器中的原始函数,它会按预期获取变量,如果模拟创建者 UID,则返回 true!但出于某种原因,在实际的应用程序访问中,如果同时调用这两个电话,就会获得未经授权的权限!
最佳答案
Firebaser在这里!
您似乎在我们的跨服务规则实现中发现了一个错误。话虽如此,您的示例将针对 Firestore 创建两次读取,但可以简化此操作以避免第二次读取。
删除第二次读取
摘自您的帖子:
return firestore.get(certification.data.creatorRef).id == request.auth.uid;
这行代码有点多余; id
字段已包含在 certification.data.creatorRef
中小路。假设您确实使用 Firestore 文档引用,格式为 creatorRef
将是/projects/<your-project-id>/databases/(default)/documents/users/<some-user-id>
。因此,您可以将函数更新为以下内容:
function userIsCreator() {
let certification = firestore.get(/databases/(default)/documents/certifications/$(certification));
let creatorRef = certification.data.creatorRef;
// Make sure to replace <your-project-id> with your project's actual ID
return creatorRef ==
/projects/<your-project-id>/databases/(default)/documents/users/$(request.auth.uid);
}
我已经在模拟器和生产中对此进行了测试,它按预期工作。这样做的好处是您只需从 Firestore 读取一次,而且它可以解决您发现的错误。
关于Firebase 跨服务安全规则在应用程序中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74039884/