Ce guide s'appuie sur le guide Firebase Security Rules pour montrer comment ajouter des conditions à vos Firebase Security Rules pour Cloud Storage.
Le composant fondamental de Cloud Storage Security Rules est la condition. Une condition est une expression booléenne qui détermine si une opération spécifique doit être autorisée ou refusée. Pour les règles de base, l'utilisation de littéraux true et false comme conditions fonctionne parfaitement. Toutefois, le Firebase Security Rules pour Cloud Storage
langage vous permet d'écrire des conditions plus complexes qui peuvent :
- vérifier l'authentification des utilisateurs ;
- valider les données entrantes.
Authentification
Firebase Security Rules pour Cloud Storage s'intègre à Firebase Authentication pour fournir une authentification puissante basée sur l'utilisateur à Cloud Storage. Cela permet un contrôle précis des accès en fonction des revendications d'un Firebase Authentication jeton.
Lorsqu'un utilisateur authentifié effectue une requête sur Cloud Storage,
la variable request.auth est renseignée avec l'uid de l'utilisateur
(request.auth.uid), ainsi qu'avec les revendications du JWT Firebase Authentication
(request.auth.token).
De plus, lorsque vous utilisez l'authentification personnalisée, des revendications supplémentaires apparaissent dans le champ request.auth.token.
Lorsqu'un utilisateur non authentifié effectue une requête, la variable request.auth est null.
À l'aide de ces données, il existe plusieurs façons courantes d'utiliser l'authentification pour sécuriser les fichiers :
- Public : ignorer
request.auth - Privé authentifié : vérifier que
request.authn'est pasnull - Privé pour l'utilisateur : vérifier que
request.auth.uidest égal à un chemin d'accèsuid - Privé pour le groupe : vérifier que les revendications du jeton personnalisé correspondent à une revendication choisie ou lire les métadonnées du fichier pour voir si un champ de métadonnées existe
Public
Toute règle qui ne tient pas compte du contexte request.auth peut être considérée comme une règle public, car elle ne tient pas compte du contexte d'authentification de l'utilisateur.
Ces règles peuvent être utiles pour afficher des données publiques telles que des éléments de jeu, des fichiers audio ou d'autres contenus statiques.
// Anyone to read a public image if the file is less than 100kB // Anyone can upload a public file ending in '.txt' match /public/{imageId} { allow read: if resource.size < 100 * 1024; allow write: if imageId.matches(".*\\.txt"); }
Privé authentifié
Dans certains cas, vous pouvez souhaiter que les données soient visibles par tous les utilisateurs authentifiés de votre application, mais pas par les utilisateurs non authentifiés. Étant donné que la variable request.auth est null pour tous les utilisateurs non authentifiés, il vous suffit de vérifier que la variable request.auth existe pour exiger une authentification :
// Require authentication on all internal image reads match /internal/{imageId} { allow read: if request.auth != null; }
Privé pour l'utilisateur
De loin, le cas d'utilisation le plus courant pour request.auth consiste à fournir aux utilisateurs individuels des autorisations précises sur leurs fichiers : de l'importation de photos de profil à la lecture de documents privés.
Étant donné que les fichiers dans Cloud Storage ont un "chemin d'accès" complet, il suffit
d'inclure des informations d'identification uniques de l'utilisateur dans le préfixe du nom de fichier (comme l'uid) qui peuvent être
vérifiées lors de l'évaluation de la règle :
// Only a user can upload their profile picture, but anyone can view it match /users/{userId}/profilePicture.png { allow read; allow write: if request.auth.uid == userId; }
Privé pour le groupe
Un autre cas d'utilisation tout aussi courant consiste à autoriser les autorisations de groupe sur un objet, par exemple en permettant à plusieurs membres d'une équipe de collaborer sur un document partagé. Pour ce faire, plusieurs approches sont possibles :
- Générer un Firebase Authentication jeton personnalisé contenant des informations supplémentaires sur un membre du groupe (comme un ID de groupe)
- Inclure des informations sur le groupe (comme un ID de groupe ou une liste d'`uid` autorisés) dans
les métadonnées du fichier
uid
Une fois ces données stockées dans le jeton ou les métadonnées du fichier, elles peuvent être référencées à partir d'une règle :
// Allow reads if the group ID in your token matches the file metadata's `owner` property // Allow writes if the group ID is in the user's custom token match /files/{groupId}/{fileName} { allow read: if resource.metadata.owner == request.auth.token.groupId; allow write: if request.auth.token.groupId == groupId; }
Évaluation des requêtes
Les importations, les téléchargements, les modifications de métadonnées et les suppressions sont évalués à l'aide des
request envoyés à Cloud Storage. En plus de l'ID unique de l'utilisateur et
la charge utile Firebase Authentication dans l'objet request.auth comme décrit ci-dessus,
la variable request contient le chemin d'accès au fichier où la requête est
effectuée, l'heure à laquelle la requête est reçue et la nouvelle valeur resource
si la requête est une écriture.
L'objet request contient également l'ID unique de l'utilisateur et la
Firebase Authentication charge utile dans l'objet request.auth, qui seront
expliqués plus en détail dans la section Sécurité basée sur l'utilisateur
de la documentation.
Vous trouverez ci-dessous la liste complète des propriétés de l'objet request :
| Propriété | Type | Description |
|---|---|---|
auth |
map<string, string> | Lorsqu'un utilisateur est connecté, fournit uid, l'ID unique de l'utilisateur, et
token, une carte des revendications JWT Firebase Authentication. Sinon, la valeur est
null. |
params |
map<string, string> | Carte contenant les paramètres de requête de la requête. |
path |
chemin d'accès | Un path représentant le chemin d'accès où la requête est effectuée. |
resource |
map<string, string> | La nouvelle valeur de la ressource, présente uniquement dans les requêtes write.
|
time |
timestamp | Un horodatage représentant l'heure du serveur à laquelle la requête est évaluée. |
Évaluation des ressources
Lors de l'évaluation des règles, vous pouvez également évaluer les métadonnées du fichier importé, téléchargé, modifié ou supprimé. Cela vous permet de créer des règles complexes et puissantes qui, par exemple, n'autorisent l'importation que des fichiers avec certains types de contenu ou la suppression que des fichiers d'une taille supérieure à une certaine taille.
Firebase Security Rules pour Cloud Storage fournit des métadonnées de fichier dans l'resource
objet, qui contient des paires clé/valeur des métadonnées affichées dans un
Cloud Storage objet. Ces propriétés peuvent être inspectées dans les requêtes read ou write pour garantir l'intégrité des données.
Dans les requêtes write (telles que les importations, les mises à jour de métadonnées et les suppressions), en
plus de l'objet resource, qui contient les métadonnées du fichier
actuellement présent dans le chemin d'accès de la requête, vous pouvez également utiliser l'objet
request.resource, qui contient un sous-ensemble des métadonnées du fichier à
écrire si l'écriture est autorisée. Vous pouvez utiliser ces deux valeurs pour garantir l'intégrité des données ou appliquer des contraintes d'application telles que le type ou la taille du fichier.
Vous trouverez ci-dessous la liste complète des propriétés de l'objet resource :
| Propriété | Type | Description |
|---|---|---|
name |
chaîne | Nom complet de l'objet |
bucket |
chaîne | Nom du bucket dans lequel se trouve cet objet. |
generation |
int | Génération de l'objet Google Cloud Storage. |
metageneration |
int | La Google Cloud Storage métagénération de l'objet. |
size |
int | Taille de l'objet en octets. |
timeCreated |
timestamp | Horodatage représentant l'heure de création d'un objet. |
updated |
timestamp | Horodatage représentant l'heure de la dernière mise à jour d'un objet. |
md5Hash |
chaîne | Hachage MD5 de l'objet. |
crc32c |
chaîne | Hachage crc32c de l'objet. |
etag |
chaîne | Etag associé à cet objet. |
contentDisposition |
chaîne | Disposition du contenu associée à cet objet. |
contentEncoding |
chaîne | Encodage du contenu associé à cet objet. |
contentLanguage |
chaîne | Langue du contenu associée à cet objet. |
contentType |
chaîne | Type de contenu associé à cet objet. |
metadata |
map<string, string> | Paires clé/valeur de métadonnées personnalisées supplémentaires spécifiées par le développeur. |
request.resource contient tous ces éléments, à l'exception de generation, metageneration, etag, timeCreated et updated.
Améliorer avec Cloud Firestore
Vous pouvez accéder aux documents dans Cloud Firestore pour évaluer d'autres critères d'autorisation.
Grâce aux fonctions firestore.get() et firestore.exists(), vos règles de sécurité
peuvent évaluer les requêtes entrantes par rapport aux documents de Cloud Firestore.
Les fonctions firestore.get() et firestore.exists() exigent des chemins d'accès de document complets. Lorsque vous utilisez des variables pour créer des chemins d'accès pour firestore.get() et firestore.exists(), vous devez explicitement échapper les variables à l'aide de la syntaxe $(variable).
Dans l'exemple ci-dessous, nous voyons une règle qui limite l'accès en lecture aux fichiers aux utilisateurs membres de clubs spécifiques.
service firebase.storage {
match /b/{bucket}/o {
match /users/{club}/files/{fileId} {
allow read: if club in
firestore.get(/databases/(default)/documents/users/$(request.auth.id)).data.memberships
}
}
}service firebase.storage {
match /b/{bucket}/o {
match /users/{userId}/photos/{fileId} {
allow read: if
firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id))
}
}
}Une fois que vous avez créé et enregistré vos premières Cloud Storage Security Rules qui utilisent ces Cloud Firestore fonctions, vous êtes invité dans la console Firebase ou l'interface de ligne de commande Firebase à activer les autorisations permettant de connecter les deux produits.
Vous pouvez désactiver cette fonctionnalité en supprimant un rôle IAM, comme décrit dans Gérer et déployer Firebase Security Rules.
Valider les données
Firebase Security Rules pour Cloud Storage peuvent également être utilisées pour la validation des données, y compris
la validation du nom et du chemin d'accès du fichier, ainsi que des propriétés des métadonnées du fichier telles que
contentType et size.
service firebase.storage { match /b/{bucket}/o { match /images/{imageId} { // Only allow uploads of any image file that's less than 5MB allow write: if request.resource.size < 5 * 1024 * 1024 && request.resource.contentType.matches('image/.*'); } } }
Fonctions personnalisées
À mesure que vos Firebase Security Rules deviennent plus complexes, vous voudrez peut-être regrouper des ensembles de conditions dans des fonctions réutilisables dans votre ensemble de règles. Les règles de sécurité sont compatibles avec les fonctions personnalisées. La syntaxe des fonctions personnalisées ressemble à JavaScript, mais les fonctions Firebase Security Rules sont écrites dans un langage propre au domaine qui présente certaines limitations importantes :
- Les fonctions ne peuvent contenir qu'une seule instruction
return. Elles ne peuvent pas contenir de logique supplémentaire. Par exemple, elles ne peuvent pas exécuter de boucles ni appeler de services externes. - Les fonctions peuvent accéder automatiquement aux fonctions et aux variables du champ d'application dans lequel elles sont définies. Par exemple, une fonction définie dans
le champ d'application
service firebase.storagea accès à laresourcevariable et, pour Cloud Firestore uniquement, aux fonctions intégrées telles queget()etexists(). - Les fonctions peuvent appeler d'autres fonctions, mais peuvent ne pas les inclure. La profondeur totale de la pile d'appel est limitée à 10.
- Dans la version
rules2, les fonctions peuvent définir des variables à l'aide du mot clélet. Les fonctions peuvent avoir n'importe quel nombre de liaisons "let", mais elles doivent se terminer par une instruction "return".
Une fonction est définie avec le mot clé function et accepte zéro ou plusieurs arguments. Par exemple, vous pouvez combiner les deux types de conditions utilisés dans les exemples ci-dessus en une seule fonction :
service firebase.storage {
match /b/{bucket}/o {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /images/{imageId} {
allow read, write: if signedInOrPublic();
}
match /mp3s/{mp3Ids} {
allow read: if signedInOrPublic();
}
}
}
L'utilisation de fonctions dans vos Firebase Security Rules les rend plus faciles à gérer à mesure que la complexité de vos règles augmente.
Étapes suivantes
Après cette discussion sur les conditions, vous avez une compréhension plus sophistiquée des règles et vous êtes prêt à :
Découvrez comment gérer les cas d'utilisation de base et le workflow de développement, de test et de déploiement des règles :
- Écrivez des règles qui traitent des scénarios courants.
- Développez vos connaissances en examinant les situations dans lesquelles vous devez identifier et éviter les règles non sécurisées.
- Testez les règles à l'aide de l'Cloud Storage émulateur et de la bibliothèque de test dédiée aux règles de sécurité.
- Consultez les méthodes disponibles pour déployer Security Rules.