Firebase 跨服务安全规则在应用程序中不起作用

标签 firebase google-cloud-firestore firebase-storage firebase-security

我正在尝试使用新的 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 相同。

enter image description here

同样的功能适用于 Firestore 规则,以避免更新认证文档(如果不是创建者),没有任何问题。

获取firestore.get后调用creatorRef似乎有问题,但没有意义!

已测试:

  1. 如果我使用 Firestore 存储规则验证器,它不会失败,并且表示我可以通过测试器中输入的 UID 访问该资源(对于其他 UID 则按预期失败)。但在我的应用程序中,即使使用创建者用户登录也会出现权限错误。

  2. 如果将函数更改为仅一次直接调用用户集合 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/

相关文章:

java - 使用 Firebase 的自定义身份验证导致 FirebaseException : An internal error has occurred. [MISSING_IDENTIFIER]

javascript - Firebase auth onCreate 将自定义用户数据添加到实时数据库

ios - Firebase 不将 URL 返回给 Swift

image - Flutter:如何使用集合内的 Firestore 字段在应用程序中上传图像

javascript - 我想将时间戳与当前时间减去一个月进行比较

android - 如何在 Android 中获取存储在 firebase 中的所有图像的 URL?

java - 将服务器时间戳字段添加到要添加的对象

database - 如何在 Cloud Firestore 中使用逻辑 OR 执行复合查询?

java - 使用 Android 时,项目似乎无法上传到 Firebase 实时数据库

javascript - 使用 VueJs 在 firebase 中上传和下载存储图像