Firebase 存储安全规则,允许访问公共文件或所有者专用文件



考虑一个允许用户将照片存储在 Firebase 存储中的应用,这些照片的用户 ID 设置在 cutom 元数据"所有者"字段中。

以下 Firebase 存储空间安全规则可确保只有他们才能看到自己的照片:

allow read: if resource.metadata.owner == request.auth.uid;

现在想象一下,该应用程序允许用户公开他们的照片,如果他们选择,任何人都可以看到,即使是未登录的用户(request.auth == null(。这可以通过另一个自定义元数据字段和一个略有不同的规则来完成:

allow read: if resource.metadata.owner == request.auth.uid || resource.metadata.public == "true";

这在理论上是可行的,但要求每次用户打开/关闭公共/私人访问时,所有照片的元数据都必须更改。

为此,可以使用以下云函数来更新给定"文件夹"下所有照片的元数据:

import * as functions from 'firebase-functions';
import * as storage from '@google-cloud/storage';
// 'data' contains 'path' of all photos to update and 'public' which will be set to "true" or "false"
export const updatePublicMetadataField = functions.https.onCall( async (data, context) => {
const s = new storage.Storage();
const bucket = s.bucket("bucket name")
const options = { prefix: data.path }
const md = { metadata: {public: data.public}}
const [files] = await bucket.getFiles(options)
for (const file of files) {
try {
await file.setMetadata(md)
} catch(error) {
return { r: 'Error: ' + error};
}
}
return { r: 'Files processed: ' + files.length};
});

这种方法的问题在于,如果用户有数百张照片,云函数将简单地超时,因为对 setMetadata 的调用速度不快。

那么有没有另一种方法可以允许打开/关闭对许多文件(都在同一个"文件夹"内(的公共访问?

我有一些目前似乎不受Firebase支持的想法是:

  1. 在同一文件夹中使用单个"安全文件",其中包含所需的元数据,可以通过 get(( 函数读取,类似于 Firestore 安全规则读取任意文档的方式。
  2. 从 Firebase 存储安全规则访问 Firestore,以允许从 Firestore 读取用户所需的"公共"值。
  3. Firebase 存储"文件夹"上的元数据。
  4. 单个(快速(函数,用于更新"文件夹"中所有文件的元数据。 例如 bucket.setMetadata(前缀,元数据(

截至目前,Firebase 存储规则不提供与 Firestore 规则相同的功能。使用 get(( 无法查询其他文档,也无法访问 Firestore 文档。您使用元数据字段的路径确实是一种合理的解决方法,尽管正如您已经指出的那样存在一些性能权衡。

为了避免Firebase函数超时,一个选项可能是使用Google Compute Instance来执行此类更新工作,可以使用您已有的代码或使用gsutil命令行工具执行此类更新工作,因为Firestore Storage支持Google Cloud Storage;最后一个选项允许进行并行元数据更新调用,如此线程所示,并在文档中进行了说明。

第二个选项可能是在检索存储照片的代码中引入条件语句,以首先从 Firestore 检查用户隐私设置并相应地继续。

第三种选择可能是使用Firestore而不是Firebase Storage,将图像保存为字节或utf-8编码的字符串数据类型,从而允许实现所需的规则。

无论如何,请记住,您始终可以打开功能请求。


编辑:我与您分享其他线程的几个链接,这些链接可能会在1,2,3后提供进一步的见解和想法。

您可以使用云函数仅更新新文件,对于旧文件,请使用 python 上的 Firebase 管理员询问,并从本地计算机更新文档,而不是使用云函数。这样,云函数就不会收到超时。

最新更新