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

Posted

技术标签:

【中文标题】Firebase 存储安全规则,允许公共或所有者私有文件访问【英文标题】:Firebase storage security rules to allow public or owner-private file access 【发布时间】:2020-03-19 05:22:50 【问题描述】:

考虑一个允许用户将照片存储在 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 支持:

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

【问题讨论】:

【参考方案1】:

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

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

第二种选择可能是在检索存储照片的代码中引入条件语句,以首先检查 Firestore 中的用户隐私设置并进行相应处理。

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

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


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

【讨论】:

【参考方案2】:

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

【讨论】:

以上是关于Firebase 存储安全规则,允许公共或所有者私有文件访问的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 存储安全规则不适用于文件夹

所有存储桶的 Firebase 存储安全规则

Firebase 存储安全规则:指定“允许读取:如果 request.auth != null”后,我仍然可以使用提供的下载链接访问我的文件

为特定用户提供访问权限的 Firebase 存储安全规则

Firebase 安全规则:只允许更新一个字段

Firebase存储安全规则为特定用户提供访问权限