Apprenez la syntaxe de base du langage Firebase Security Rules for Cloud Storage

Les règles de sécurité Firebase pour Cloud Storage vous permettent de contrôler l'accès aux objets stockés dans les buckets Cloud Storage. La syntaxe des règles flexibles vous permet de créer des règles pour contrôler n'importe quelle opération, depuis toutes les écritures dans votre bucket Cloud Storage jusqu'aux opérations sur un fichier spécifique.

Ce guide décrit la syntaxe et la structure de base des règles de sécurité Cloud Storage pour créer des ensembles de règles complets.

Déclaration de service et de base de données

Les règles de sécurité Firebase pour Cloud Storage commencent toujours par la déclaration suivante :

service firebase.storage {
    // ...
}

La déclaration du service firebase.storage étend les règles à Cloud Storage, évitant ainsi les conflits entre les règles de sécurité Cloud Storage et les règles d'autres produits tels que Cloud Firestore.

Règles de lecture/écriture de base

Les règles de base consistent en une instruction match identifiant les buckets Cloud Storage, une instruction de correspondance spécifiant un nom de fichier et une expression allow détaillant le moment où la lecture des données spécifiées est autorisée. Les expressions allow spécifient les méthodes d'accès (par exemple, lecture, écriture) impliquées et les conditions dans lesquelles l'accès est autorisé ou refusé.

Dans votre ensemble de règles par défaut, la première instruction match utilise une expression générique {bucket} pour indiquer que les règles s'appliquent à tous les compartiments de votre projet. Nous discuterons davantage de l’idée des correspondances génériques dans la section suivante.

service firebase.storage {
  // The {bucket} wildcard indicates we match files in all Cloud Storage buckets
  match /b/{bucket}/o {
    // Match filename
    match /filename {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

Toutes les instructions de correspondance pointent vers des fichiers. Une instruction match peut pointer vers un fichier spécifique, comme dans match /images/profilePhoto.png .

Faire correspondre les caractères génériques

En plus de pointer vers un seul fichier, les règles peuvent utiliser des caractères génériques pour pointer vers n'importe quel fichier avec un préfixe de chaîne donné dans son nom, y compris des barres obliques, comme dans match /images/{imageId} .

Dans l'exemple ci-dessus, l'instruction match utilise la syntaxe générique {imageId} . Cela signifie que la règle s'applique à tout fichier avec /images/ au début de son nom, tel que /images/profilePhoto.png ou /images/croppedProfilePhoto.png . Lorsque les expressions allow dans l'instruction match sont évaluées, la variable imageId sera résolue en nom de fichier image, tel que profilePhoto.png ou croppedProfilePhoto.png .

Une variable générique peut être référencée à partir de la match pour fournir un nom de fichier ou une autorisation de chemin :

// Another way to restrict the name of a file
match /images/{imageId} {
  allow read: if imageId == "profilePhoto.png";
}

Données hiérarchiques

Comme nous l'avons déjà dit, il n'y a pas de structure hiérarchique à l'intérieur d'un bucket Cloud Storage. Mais en utilisant une convention de dénomination de fichiers, qui inclut souvent des barres obliques dans les noms de fichiers, nous pouvons imiter une structure qui ressemble à une série imbriquée de répertoires et de sous-répertoires. Il est important de comprendre comment les règles de sécurité Firebase interagissent avec ces noms de fichiers.

Considérons la situation d'un ensemble de fichiers dont les noms commencent tous par le radical /images/ . Les règles de sécurité Firebase s'appliquent uniquement au nom de fichier correspondant, de sorte que les contrôles d'accès définis sur la tige /images/ ne s'appliquent pas à la tige /mp3s/ . Au lieu de cela, écrivez des règles explicites qui correspondent à différents modèles de nom de fichier :

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      allow read, write: if <condition>;
    }

    // Explicitly define rules for the 'mp3s' pattern
    match /mp3s/{mp3Id} {
      allow read, write: if <condition>;
    }
  }
}

Lors de l'imbrication d'instructions match , le chemin de l'instruction match interne est toujours ajouté au chemin de l'instruction match externe. Les deux ensembles de règles suivants sont donc équivalents :

service firebase.storage {
  match /b/{bucket}/o {
    match /images {
      // Exact match for "images/profilePhoto.png"
      match /profilePhoto.png {
        allow write: if <condition>;
      }
    }
  }
}
service firebase.storage {
  match /b/{bucket}/o {
    // Exact match for "images/profilePhoto.png"
    match /images/profilePhoto.png {
      allow write: if <condition>;
      }
  }
}

Caractères génériques de correspondance récursive

En plus des caractères génériques qui correspondent et renvoient des chaînes à la fin d'un nom de fichier, un caractère générique à plusieurs segments peut être déclaré pour une correspondance plus complexe en ajoutant =** au nom du caractère générique, comme {path=**} :

// Partial match for files that start with "images"
match /images {

  // Exact match for "images/**"
  // e.g. images/users/user:12345/profilePhoto.png is matched
  // images/profilePhoto.png is also matched!
  match /{allImages=**} {
    // This rule matches one or more path segments (**)
    // allImages is a path that contains all segments matched
    allow read: if <other_condition>;
  }
}

Si plusieurs règles correspondent à un fichier, le résultat est le OR du résultat de toutes les évaluations de règles. Autrement dit, si une règle à laquelle le fichier correspond est évaluée à true , le résultat est true .

Dans les règles ci-dessus, le fichier "images/profilePhoto.png" peut être lu si condition ou other_condition est évaluée à true, tandis que le fichier "images/users/user:12345/profilePhoto.png" n'est soumis qu'au résultat de other_condition .

Les règles de sécurité Cloud Storage ne sont pas appliquées en cascade et les règles ne sont évaluées que lorsque le chemin de la requête correspond à un chemin avec les règles spécifiées.

Version 1

Les règles de sécurité Firebase utilisent la version 1 par défaut. Dans la version 1, les caractères génériques récursifs correspondent à un ou plusieurs éléments de nom de fichier, et non à zéro ou plusieurs éléments. Ainsi, match /images/{filenamePrefixWildcard}/{imageFilename=**} correspond à un nom de fichier comme /images/profilePics/profile.png, mais pas /images/badge.png. Utilisez /images/{imagePrefixorFilename=**} à la place.

Les caractères génériques récursifs doivent figurer à la fin d'une instruction de correspondance.

Nous vous recommandons d'utiliser la version 2 pour ses fonctionnalités plus puissantes.

Version 2

Dans la version 2 des règles de sécurité Firebase, les caractères génériques récursifs correspondent à zéro ou plusieurs éléments de chemin. Ainsi, /images/{filenamePrefixWildcard}/{imageFilename=**} correspond aux noms de fichiers /images/profilePics/profile.png et /images/badge.png.

Vous devez vous inscrire à la version 2 en ajoutant rules_version = '2'; en haut de vos règles de sécurité :

rules_version = '2';
service cloud.storage {
  match /b/{bucket}/o {
   ...
 }
}

Vous pouvez avoir au plus un caractère générique récursif par instruction de correspondance, mais dans la version 2, vous pouvez placer ce caractère générique n'importe où dans l'instruction de correspondance. Par exemple:

rules_version = '2';
service firebase.storage {
 match /b/{bucket}/o {
   // Matches any file in a songs "subdirectory" under the
   // top level of your Cloud Storage bucket.
   match /{prefixSegment=**}/songs/{mp3filenames} {
     allow read, write: if <condition>;
   }
  }
}

Opérations granulaires

Dans certaines situations, il est utile de diviser read et write en opérations plus granulaires. Par exemple, votre application souhaitera peut-être appliquer des conditions différentes lors de la création de fichiers et lors de leur suppression.

Une opération read peut être divisée en get et list .

Une règle write peut être divisée en create , update et delete :

service firebase.storage {
  match /b/{bucket}/o {
    // A read rule can be divided into read and list rules
    match /images/{imageId} {
      // Applies to single file read requests
      allow get: if <condition>;
      // Applies to list and listAll requests (Rules Version 2)
      allow list: if <condition>;

    // A write rule can be divided into create, update, and delete rules
    match /images/{imageId} {
      // Applies to writes to file contents
      allow create: if <condition>;

      // Applies to updates to (pre-existing) file metadata
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
 }
}

Déclarations de correspondance qui se chevauchent

Il est possible qu'un nom de fichier corresponde à plusieurs instructions match . Dans le cas où plusieurs expressions allow correspondent à une requête, l'accès est autorisé si l'une des conditions est true :

service firebase.storage {
  match b/{bucket}/o {
    // Matches file names directly inside of '/images/'.
    match /images/{imageId} {
      allow read, write: if false;
    }

    // Matches file names anywhere under `/images/`
    match /images/{imageId=**} {
      allow read, write: if true;
    }
  }
}

Dans l'exemple ci-dessus, toutes les lectures et écritures dans les fichiers dont le nom commence par /images/ sont autorisées car la deuxième règle est toujours true , même lorsque la première règle est false .

Les règles ne sont pas des filtres

Une fois que vous avez sécurisé vos données et commencé à effectuer des opérations sur les fichiers, gardez à l’esprit que les règles de sécurité ne sont pas des filtres. Vous ne pouvez pas effectuer d'opérations sur un ensemble de fichiers correspondant à un modèle de nom de fichier et vous attendre à ce que Cloud Storage accède uniquement aux fichiers auxquels le client actuel est autorisé à accéder.

Par exemple, prenons la règle de sécurité suivante :

service firebase.storage {
  match /b/{bucket}/o {
    // Allow the client to read files with contentType 'image/png'
    match /aFileNamePrefix/{aFileName} {
      allow read: if resource.contentType == 'image/png';
    }
  }
}

Refusé : cette règle rejette la demande suivante car le jeu de résultats peut inclure des fichiers où contentType n'est pas image/png :

la toile
filesRef = storage.ref().child("aFilenamePrefix");

filesRef.listAll()
    .then(function(result) {
      console.log("Success: ", result.items);
    })
});

Les règles des règles de sécurité du stockage cloud évaluent chaque requête par rapport à son résultat potentiel et échouent si la requête peut renvoyer un fichier que le client n'est pas autorisé à lire. Les demandes d'accès doivent suivre les contraintes fixées par vos règles.

Prochaines étapes

Vous pouvez approfondir votre compréhension des règles de sécurité Firebase pour le stockage cloud :

  • Découvrez le prochain concept majeur du langage des règles, les conditions dynamiques, qui permettent à vos règles de vérifier l'autorisation des utilisateurs, de comparer les données existantes et entrantes, de valider les données entrantes, et bien plus encore.

  • Passez en revue les cas d'utilisation typiques de la sécurité et les définitions des règles de sécurité Firebase qui les traitent .

Vous pouvez explorer les cas d'utilisation des règles de sécurité Firebase spécifiques au stockage cloud :