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