问题
I'm building an Android app which requires me to store some pictures for the user.
Let's say I have 2 users: A and B. They should be able to read / write on their specific folders: user A can read and write to bucket/images/userA and user B can read and write to bucket/images/userB. They should not have access to anything else.
Now let's say user A uploaded picture1.jpg and picture2.jpg. How can user A grant access to bucket/images/userA/picture1.jpg to user B? User B should not have access to picture2.jpg though.
I'm looking for a solution that scales for many users (~100.000+). I suppose it's not a great idea to add a rule to the storage rules every time I want to give access to a file.
The solution I use right now is anyone logged in can read anything if they have the full path to it. The path is not easy to guess and when I want to give access I provide the link. Is that a secure enough solution? I don't think so.
回答1:
On the client side
You can use custom File Metadata for that. What it does it is adds a Map<String, String>
to the file's metadata. And since keys in a Map are unique, you can store the user B's id as a key and use an empty string as value:
StorageMetadata metadata = new StorageMetadata.Builder()
.setCustomMetadata(userId,"") //User B's id
.build();
Then use the updateMetadata()
method to share the file:
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!
}
});
On the Firebase Console
Then in order to validate this on the Firebase side, you can set your rules as following:
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();
}
}
}
Share with more users
If you want to share this same file with more users (let's say user C and D), you can repeat the same steps passing their ids to the custom metadata, because only the properties specified in the metadata are updated and all others are left unmodified.
Revoke user access
If you want to revoke access from a specific user, you can set a null value to the custom metadata and call the updateMetadata()
once again.
StorageMetadata metadata = new StorageMetadata.Builder()
.setCustomMetadata(userId, null)
.build();
来源:https://stackoverflow.com/questions/39549334/firebase-rules-dynamically-give-access-to-a-specific-user