Utiliser des conditions dans les règles de sécurité Firebase Cloud Storage

Ce guide s'appuie sur l'apprentissage de la syntaxe de base du guide sur le langage Firebase Security Rules. pour montrer comment ajouter des conditions à votre Firebase Security Rules pour Cloud Storage.

La condition est le composant principal de Cloud Storage Security Rules. 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, utiliser des littéraux true et false que les conditions fonctionnent parfaitement. En revanche, 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 pour Cloud Storage. Cela permet un contrôle d'accès précis basé sur les revendications d'un jeton Firebase Authentication.

Lorsqu'un utilisateur authentifié exécute une requête sur Cloud Storage, La variable request.auth est renseignée avec la valeur uid de l'utilisateur. (request.auth.uid), ainsi que les revendications du jeton JWT Firebase Authentication (request.auth.token).

De plus, lorsque vous utilisez l'authentification personnalisée, d'autres revendications sont émises 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 :

  • Public : ignorer request.auth
  • Authentification privée: vérifiez que request.auth n'est pas null
  • Utilisateur privé: vérifiez que request.auth.uid est égal à un chemin d'accès uid.
  • Groupe privé: vérifiez que les revendications du jeton personnalisé correspondent à la revendication choisie. 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 public, car elle ne prend pas en compte le contexte d'authentification de l'utilisateur. Ces règles peuvent être utiles pour afficher des données publiques, comme les éléments de jeu, ou tout autre contenu statique.

// 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ée authentifiée

Dans certains cas, vous pouvez souhaiter que les données soient visibles par tous les utilisateurs authentifiés de votre application, mais pas par des utilisateurs non authentifiés. Depuis le request.auth est null pour tous les utilisateurs non authentifiés, il vous suffit de vérifier 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;
}

Utilisateur privé

Le cas d'utilisation de request.auth le plus courant consiste, de loin, à fournir aux utilisateurs aux utilisateurs disposant d'autorisations précises sur leurs fichiers, qu'il s'agisse de l'importation de photos de profil, à la lecture de documents privés.

Les fichiers du domaine Cloud Storage ayant un "chemin d'accès" complet au fichier, il n'y a qu'un seul pour qu'un fichier soit contrôlé par un utilisateur, il s'agit d'un élément unique permettant des informations dans le préfixe du nom de fichier (telles que le uid de l'utilisateur) pouvant être vérifié 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;
}

Groupe privé

Un autre cas d'utilisation tout aussi courant consiste à autoriser des autorisations de groupe sur un objet, par exemple en autorisant plusieurs membres d'une équipe à collaborer sur un document partagé. Il y Pour ce faire, plusieurs approches s'offrent à vous:

  • Générer un jeton personnalisé Firebase Authentication contenant des informations supplémentaires sur un membre du groupe (comme un ID de groupe)
  • Incluez des informations sur le groupe (comme un ID de groupe ou une liste de uid autorisés) dans les métadonnées du fichier

Une fois ces données stockées dans les métadonnées du jeton ou du fichier, elles peuvent être référencées dans 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;
}

Demander une évaluation

Les importations, les téléchargements, les modifications de métadonnées et les suppressions sont évalués à l'aide de l'request envoyé à Cloud Storage. En plus de l'identifiant 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 dans lequel la requête est envoyée l'heure de réception de la requête et la nouvelle valeur resource si la requête est une écriture.

L'objet request contient également l'identifiant unique de l'utilisateur et le la charge utile Firebase Authentication dans l'objet request.auth, qui sera dans l'article sur la 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<chaîne, chaîne> Lorsqu'un utilisateur est connecté, fournit uid, son identifiant unique et token, une carte de Firebase Authentication revendications JWT. Sinon, il s'agit de null
params map<chaîne, chaîne> Carte contenant les paramètres de la requête.
path chemin d'accès Un path représentant le chemin d'accès de la requête à l'issue de ce cours.
resource map<chaîne, chaîne> Nouvelle valeur de la ressource, présente uniquement dans les requêtes write.
time timestamp Code temporel 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 en cours d'importation, de téléchargement, de modification ou de suppression. Cela vous permet de créer des règles complexes et performantes, par exemple, n'autoriser que les fichiers contenant de types de contenu à importer, ou uniquement les fichiers dont la taille dépasse un certain seuil supprimés.

Firebase Security Rules pour Cloud Storage fournit des métadonnées de fichier dans l'objet resource, qui contient des paires clé/valeur des métadonnées affichées dans un objet Cloud Storage. Ces propriétés peuvent être inspectées sur les requêtes read ou write pour garantir l'intégrité des données.

Pour 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 existant actuellement sur le chemin 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 vous assurer que les données l'intégrité 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 Le nom complet de l'objet
bucket chaîne Nom du bucket dans lequel se trouve cet objet.
generation int Le Google Cloud Storage génération de l'objet de cet objet.
metageneration int Le Google Cloud Storage métagénération de cet objet.
size int La taille de l'objet en octets.
timeCreated timestamp Code temporel représentant l'heure de création d'un objet.
updated timestamp Code temporel 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<chaîne, chaîne> 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 autorisations critères.

À l'aide des fonctions firestore.get() et firestore.exists(), votre sécurité peuvent évaluer les requêtes entrantes par rapport aux documents dans Cloud Firestore. Les fonctions firestore.get() et firestore.exists() attendent toutes deux chemins d'accès spécifiés pour le document. 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, une règle restreint l'accès en lecture aux fichiers les utilisateurs membres de certains clubs.

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)).memberships
    }
  }
}
Dans l'exemple suivant, seuls les amis d'un utilisateur peuvent voir ses photos.
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))
    }
  }
}

Après avoir créé et enregistré vos premiers Cloud Storage Security Rules utilisant ces Cloud Firestore vous serez invité dans la console Firebase ou la CLI Firebase pour activer les autorisations pour connecter les deux produits.

Vous pouvez désactiver la fonctionnalité en supprimant un rôle IAM, comme décrit dans la section Gérer et déployer Firebase Security Rules.

Valider les données

Firebase Security Rules pour Cloud Storage peut également être utilisé pour la validation des données, y compris en validant le nom et le chemin d'un fichier, ainsi que les propriétés des métadonnées de 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 votre Firebase Security Rules devient plus complexe, vous pouvez envelopper des ensembles de des conditions dans des fonctions réutilisables dans l'ensemble de règles. Les règles de sécurité sont compatibles avec les fonctions personnalisées. La syntaxe des fonctions personnalisées est semblable à celle du JavaScript, Toutefois, les fonctions Firebase Security Rules sont écrites dans un langage propre au domaine qui présente certaines limites importantes:

  • Les fonctions ne peuvent contenir qu'une seule instruction return. Elles ne peuvent pas contenir de logique supplémentaire. Par exemple, ils ne peuvent pas exécuter de boucles ou appeler des 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 niveau d'accès service firebase.storage a accès aux la variable resource, et pour Cloud Firestore uniquement, les fonctions intégrées comme get() et exists().
  • 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 un nombre illimité de liaisons "let", mais elles doivent se terminer par un retour .

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 votre Firebase Security Rules les rend plus faciles à gérer, car leur complexité de vos règles s'accroît.

Étapes suivantes

Après cette discussion sur les conditions, vous avez une compréhension plus approfondie des règles et vous êtes prêt à :

Apprenez à gérer les principaux cas d'utilisation et découvrez le workflow de développement, pour tester et déployer des règles: