我正在开发一个android应用程序,它要求我为用户存储一些图片。
假设我有两个用户:a和b。他们应该能够读/写他们的特定文件夹:用户a可以读/写bucket/images/usera和用户b可以读/写bucket/images/userb。他们不应该接触到其他任何东西。
现在假设用户a上传了picture1.jpg和picture2.jpg。用户a如何向用户b授予bucket/images/usera/picture1.jpg的访问权限?但是,用户B不应该有权访问picture2.jpg。
我正在寻找一个可扩展到许多用户(~100.000+)的解决方案。我想,每次我想授予对文件的访问权限时,在存储规则中添加规则并不是一个好主意。
我现在使用的解决方案是,任何登录的人都可以读取任何内容,如果他们有完整的路径。路径不容易猜测,当我想提供访问权限时,我会提供链接。这是一个足够安全的解决方案吗?我不这么认为。
最佳答案
在客户端
你可以这样做。它所做的是将Map<String, String>
添加到文件的元数据中。由于映射中的键是唯一的,因此可以将用户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();