【问题标题】:Firebase rules: dynamically give access to a specific userFirebase 规则:动态授予特定用户访问权限
【发布时间】:2017-01-25 17:40:11
【问题描述】:

我正在构建一个 Android 应用,它需要我为用户存储一些图片。

假设我有 2 个用户:A 和 B。他们应该能够读取/写入其特定文件夹:用户 A 可以读取和写入 bucket/images/userA,用户 B 可以读取和写入 bucket/images /用户B。他们不应该访问其他任何东西。

现在假设用户 A 上传了图片 1.jpg 和图片 2.jpg。用户 A 如何将 bucket/images/userA/picture1.jpg 的访问权限授予用户 B?用户 B 不应该访问 picture2.jpg。

我正在寻找一种适用于许多用户 (~100.000+) 的解决方案。我想每次我想授予文件访问权限时都向存储规则添加规则不是一个好主意。

我现在使用的解决方案是任何登录的人都可以阅读任何内容,只要他们有完整的路径即可。路径不容易猜到,当我想提供访问权限时,我会提供链接。这是一个足够安全的解决方案吗?我不这么认为。

【问题讨论】:

    标签: android firebase firebase-security firebase-storage


    【解决方案1】:

    在客户端

    您可以为此use custom File Metadata。它的作用是将Map<String, String> 添加到文件的元数据中。并且由于 Map 中的键是唯一的,您可以将用户 B 的 id 存储为键并使用空字符串作为值:

    StorageMetadata metadata = new StorageMetadata.Builder()
                            .setCustomMetadata(userId,"") //User B's id
                            .build();
    

    然后使用updateMetadata()方法分享文件:

    picture1Ref.updateMetadata(metadata)
            .addOnSuccessListener(new OnSuccessListener<StorageMetadata>() {
                @Override
                public void onSuccess(StorageMetadata storageMetadata) {
                    // Updated metadata is in storageMetadata
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception exception) {
                    // Uh-oh, an error occurred!
                }
            });
    

    在 Firebase 控制台上

    然后为了在 Firebase 端验证这一点,您可以设置如下规则:

    service firebase.storage {
      match /b/{bucket}/o {
        match /images/{userId}/{pictureName}{
          allow write: if request.auth.uid == userId;
          allow read: if request.auth.uid == userId || request.auth.uid in resource.metadata.keys();
        }
      }
    }
    

    与更多用户分享

    如果您想与更多用户(比如用户 C 和 D)共享同一个文件,您可以重复相同的步骤,将他们的 id 传递给自定义元数据,因为只有元数据中指定的属性会被更新,而所有其他的保持不变。

    撤销用户访问权限

    如果您想撤销特定用户的访问权限,您可以将自定义元数据设置为空值并再次调用updateMetadata()

    StorageMetadata metadata = new StorageMetadata.Builder()
                            .setCustomMetadata(userId, null)
                            .build();
    

    【讨论】:

    • 我很久以前就需要了哈哈,但谢谢!我不知道我是否应该将它标记为已回答,因为这个项目已经死了,我没有办法测试它。不过听起来不错。
    • 哈哈,我知道这是个老问题了。我在开发类似项目时遇到了这篇文章。所以现在我找到了解决方案,我决定在这里发布。对我来说效果很好;)
    猜你喜欢
    • 2011-08-30
    • 2020-08-15
    • 2021-07-06
    • 2016-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多