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

时间:2019-11-23 09:03:59

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

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

以下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中读取用户所需的“ public”值。
  3. Firebase存储“文件夹”上的元数据。
  4. 单个(快速)功能,用于更新“文件夹”中所有文件的元数据。例如。 bucket.setMetadata(前缀,元数据)

2 个答案:

答案 0 :(得分:0)

到目前为止,Firebase存储规则所提供的功能与Firestore规则不同。无法使用get()查询其他文档或访问Firestore文档。尽管您已经注意到一些性能折衷,但您使用元数据字段的路径确实是一种合理的解决方法。

为避免Firebase功能超时,一个选项可能是使用Google Compute Instance来对已有的代码或gsutil命令行工具进行此类更新,因为Firestore Storage为backed on Google Cloud Storage;最后一个选项允许进行并行元数据更新调用,如本thread中所示和documentation中所述。

第二种选择是在代码中引入条件语句,该条件语句检索存储照片,以便首先从Firestore检查用户隐私设置,然后进行相应操作。

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

无论如何,请记住您可以随时打开feature request


编辑:我与您分享其他主题的一些链接,这些链接可能会提供进一步的见解和构想post-1post-2post-3

答案 1 :(得分:0)

您可以使用云功能仅更新新文件,而对于较旧的文件,请在python上使用firebase admin ask并从本地计算机更新文档,而不使用云功能。这样,云功能就不会收到超时。