Check out what’s new from Firebase@ Google I/O 2021, and join our alpha program for early access to the new Remote Config personalization feature. Learn more

Langue des règles de sécurité

Les règles de sécurité Firebase s'appuient sur des langages flexibles, puissants et personnalisés qui prennent en charge un large éventail de complexité et de granularité. Vous pouvez rendre vos règles aussi spécifiques ou aussi générales que logique pour votre application. Les règles de base de données en temps réel utilisent une syntaxe qui ressemble à JavaScript dans une structure JSON. Les règles Cloud Firestore et Cloud Storage utilisent un langage basé sur le Common Expression Language (CEL) , qui s'appuie sur CEL avec des instructions match et allow qui prennent en charge l'accès accordé sous condition.

Comme il s'agit de langages personnalisés, il existe cependant une courbe d'apprentissage. Utilisez ce guide pour mieux comprendre le langage des règles tout en approfondissant des règles plus complexes.

Sélectionnez un produit pour en savoir plus sur ses règles.

Structure basique

Cloud Firestore

Les règles de sécurité Firebase dans Cloud Firestore et Cloud Storage utilisent la structure et la syntaxe suivantes :

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

Les concepts clés suivants sont importants à comprendre lorsque vous créez les règles :

  • Requête : la ou les méthodes invoquées dans l'instruction allow . Ce sont des méthodes que vous autorisez à exécuter. Les méthodes standard sont : get , list , create , update et delete . Les méthodes pratiques de read et d' write permettent un large accès en lecture et en écriture sur la base de données ou le chemin de stockage spécifié.
  • Chemin : la base de données ou l'emplacement de stockage, représenté sous la forme d'un chemin URI.
  • Règle : l' instruction allow , qui inclut une condition qui autorise une requête si elle est évaluée à true.

Chacun de ces concepts est décrit plus en détail ci-dessous.

Stockage en ligne

Les règles de sécurité Firebase dans Cloud Firestore et Cloud Storage utilisent la structure et la syntaxe suivantes :

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

Les concepts clés suivants sont importants à comprendre lorsque vous créez les règles :

  • Requête : la ou les méthodes invoquées dans l'instruction allow . Ce sont des méthodes que vous autorisez à exécuter. Les méthodes standard sont : get , list , create , update et delete . Les méthodes pratiques de read et d' write permettent un large accès en lecture et en écriture sur la base de données ou le chemin de stockage spécifié.
  • Chemin : la base de données ou l'emplacement de stockage, représenté sous la forme d'un chemin URI.
  • Règle : l' instruction allow , qui inclut une condition qui autorise une requête si elle est évaluée à true.

Chacun de ces concepts est décrit plus en détail ci-dessous.

Base de données en temps réel

Dans Realtime Database, les règles de sécurité Firebase se composent d'expressions de type JavaScript contenues dans un document JSON.

Ils utilisent la syntaxe suivante :

{
  "rules": {
    "<<path>>": {
    // Allow the request if the condition for each method is true.
      ".read": <<condition>>,
      ".write": <<condition>>,
      ".validate": <<condition>>
    }
  }
}

Il y a trois éléments de base dans la règle :

  • Chemin : l' emplacement de la base de données. Cela reflète la structure JSON de votre base de données.
  • Demande : il s'agit des méthodes utilisées par la règle pour accorder l'accès. Les règles de read et d' write accordent un large accès en lecture et en écriture, tandis que les règles de validate agissent comme une vérification secondaire pour accorder l'accès en fonction des données entrantes ou existantes.
  • Condition : la condition qui autorise une demande si elle est évaluée à true.

Constructions de règles

Cloud Firestore

Les éléments de base d'une règle dans Cloud Firestore et Cloud Storage sont les suivants :

  • La déclaration de service : déclare le produit Firebase auquel les règles s'appliquent.
  • Le bloc de match : définit un chemin dans la base de données ou le compartiment de stockage auquel les règles s'appliquent.
  • L'instruction allow : fournit les conditions d'octroi de l'accès, différenciées par les méthodes. Les méthodes prises en charge incluent : get , list , create , update , delete et les méthodes de commodité read et write .
  • Déclarations de function facultatives : offrent la possibilité de combiner et d'encapsuler des conditions à utiliser dans plusieurs règles.

Le service contient un ou plusieurs blocs de match avec des instructions allow qui fournissent des conditions accordant l'accès aux requêtes. Les variables de request et de resource peuvent être utilisées dans des conditions de règle. Le langage Firebase Security Rules prend également en charge function déclarations de function .

Version de la syntaxe

L'instruction de syntax indique la version du langage Firebase Rules utilisé pour écrire la source. La dernière version de la langue est v2 .

rules_version = '2';
service cloud.firestore {
...
}

Si aucune instruction rules_version n'est fournie, vos règles seront évaluées à l'aide du moteur v1 .

Un service

La déclaration de service définit à quel produit ou service Firebase vos règles s'appliquent. Vous ne pouvez inclure qu'une seule déclaration de service par fichier source.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Stockage en ligne

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

Si vous définissez des règles pour Cloud Firestore et Cloud Storage à l'aide de la CLI Firebase, vous devrez les conserver dans des fichiers séparés.

Correspondre

Un bloc de match déclare un modèle de path qui correspond au chemin de l'opération demandée (le request.path entrant ). Le corps de la match doit avoir un ou plusieurs blocs de match imbriqués, des instructions allow ou function déclarations de function . Le chemin dans les blocs de match imbriqués est relatif au chemin dans le bloc de match parent.

Le modèle de path est un nom de type répertoire qui peut inclure des variables ou des caractères génériques. Le modèle de path permet des correspondances de segment à chemin unique et de segment à chemins multiples. Toutes les variables liées dans un path sont visibles dans la portée de match ou dans toute portée imbriquée où le path est déclaré.

Les correspondances avec un modèle de path peuvent être partielles ou complètes :

  • Correspondances partielles : le modèle de path est une correspondance de préfixe de request.path .
  • Correspondances complètes : le modèle de path correspond à l'intégralité de request.path .

Lorsqu'une correspondance complète est établie, les règles du bloc sont évaluées. Lorsqu'une correspondance partielle est établie, les règles de match imbriquées sont testées pour voir si un path imbriqué terminera la correspondance.

Les règles de chaque match complète sont évaluées pour déterminer s'il faut autoriser la demande. Si une règle de correspondance accorde l'accès, la demande est autorisée. Si aucune règle de correspondance n'accorde l'accès, la demande est refusée.

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

Comme le montre l'exemple ci-dessus, les déclarations de path prennent en charge les variables suivantes :

  • Caractère générique à un seul segment : une variable générique est déclarée dans un chemin en enveloppant une variable entre accolades : {variable} . Cette variable est accessible dans l'instruction match sous forme de string .
  • Caractère générique récursif : le caractère générique récursif, ou multi-segment, correspond à plusieurs segments de chemin au niveau ou au-dessous d'un chemin. Ce caractère générique correspond à tous les chemins situés sous l'emplacement auquel vous l'avez défini. Vous pouvez le déclarer en ajoutant la chaîne =** à la fin de votre variable de segment : {variable=**} . Cette variable est accessible dans l'instruction match tant qu'objet path .

Permettre

Le bloc match contient une ou plusieurs instructions allow . Ce sont vos règles réelles. Vous pouvez appliquer des règles d' allow à une ou plusieurs méthodes. Les conditions d'une instruction allow doivent avoir la valeur true pour que Cloud Firestore ou Cloud Storage accepte toute requête entrante. Vous pouvez également écrire des instructions allow sans conditions, par exemple allow read . Si l'instruction allow n'inclut pas de condition, cependant, elle autorise toujours la requête pour cette méthode.

Si l'une des règles d' allow de la méthode est satisfaite, la demande est autorisée. De plus, si une règle plus large accorde l'accès, les règles accordent l'accès et ignorent les règles plus granulaires qui pourraient limiter l'accès.

Considérez l'exemple suivant, où n'importe quel utilisateur peut lire ou supprimer n'importe lequel de ses propres fichiers. Une règle plus précise n'autorise les écritures que si l'utilisateur qui demande l'écriture possède le fichier et que le fichier est au format PNG. Un utilisateur peut supprimer tous les fichiers du sous-chemin, même s'il ne s'agit pas de fichiers PNG, car la règle précédente le permet.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

Méthode

Chaque instruction allow inclut une méthode qui accorde l'accès aux demandes entrantes de la même méthode.

Méthode Type de demande
Méthodes pratiques
read Tout type de demande de lecture
write Tout type de demande d'écriture
Méthodes standard
get Lire les demandes de documents ou de fichiers uniques
list Lire les demandes de requêtes et de collectes
create Écrire de nouveaux documents ou fichiers
update Écrire dans des documents ou des fichiers existants
delete Suprimmer les données

Vous ne pouvez pas chevaucher des méthodes de lecture dans le même bloc de match ou des méthodes d'écriture en conflit dans la même déclaration de path .

Par exemple, les règles suivantes échoueraient :

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

Une fonction

Au fur et à mesure que vos règles de sécurité deviennent plus complexes, vous souhaiterez peut-être encapsuler des ensembles de conditions dans des fonctions que vous pourrez réutiliser dans votre ensemble de règles. Les règles de sécurité prennent en charge les fonctions personnalisées. La syntaxe des fonctions personnalisées ressemble un peu à JavaScript, mais les fonctions de règles de sécurité sont écrites dans un langage spécifique à un domaine qui présente des limitations importantes :

  • Les fonctions ne peuvent contenir qu'une seule instruction return . Ils 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 variables à partir de la portée dans laquelle elles sont définies. Par exemple, une fonction définie dans la portée du service cloud.firestore a accès à la variable de resource et aux fonctions intégrées telles que get() et exists() .
  • Les fonctions peuvent appeler d'autres fonctions mais ne peuvent pas se reproduire. La profondeur totale de la pile d'appels est limitée à 20.
  • Dans la version v2 règles, les fonctions peuvent définir des variables à l'aide du mot let clé let . Les fonctions peuvent avoir jusqu'à 10 liaisons let, mais doivent se terminer par une instruction return.

Une fonction est définie avec le mot-clé function et prend zéro ou plusieurs arguments. Par exemple, vous pouvez combiner les deux types de conditions utilisées dans les exemples ci-dessus en une seule fonction :

service cloud.firestore {
  match /databases/{database}/documents {
    // 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 /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

Voici un exemple montrant les arguments de fonction et les affectations let. Les instructions d'affectation Let doivent être séparées par des points-virgules.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

Notez comment l'affectation isAdmin applique une recherche de la collection admins. Pour une évaluation paresseuse sans nécessiter de recherches inutiles, profitez de la nature court-circuitante de && (AND) et || (OR) pour appeler une deuxième fonction uniquement si isAuthor est vrai (pour les comparaisons && ) ou faux (pour les comparaisons || ).

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

L'utilisation de fonctions dans vos règles de sécurité les rend plus faciles à gérer à mesure que la complexité de vos règles augmente.

Stockage en ligne

Les éléments de base d'une règle dans Cloud Firestore et Cloud Storage sont les suivants :

  • La déclaration de service : déclare le produit Firebase auquel les règles s'appliquent.
  • Le bloc de match : définit un chemin dans la base de données ou le compartiment de stockage auquel les règles s'appliquent.
  • L'instruction allow : fournit les conditions d'octroi de l'accès, différenciées par les méthodes. Les méthodes prises en charge incluent : get , list , create , update , delete et les méthodes de commodité read et write .
  • Déclarations de function facultatives : offrent la possibilité de combiner et d'encapsuler des conditions à utiliser dans plusieurs règles.

Le service contient un ou plusieurs blocs de match avec des instructions allow qui fournissent des conditions accordant l'accès aux requêtes. Les variables de request et de resource peuvent être utilisées dans des conditions de règle. Le langage Firebase Security Rules prend également en charge function déclarations de function .

Version de la syntaxe

L'instruction de syntax indique la version du langage Firebase Rules utilisé pour écrire la source. La dernière version de la langue est v2 .

rules_version = '2';
service cloud.firestore {
...
}

Si aucune instruction rules_version n'est fournie, vos règles seront évaluées à l'aide du moteur v1 .

Un service

La déclaration de service définit à quel produit ou service Firebase vos règles s'appliquent. Vous ne pouvez inclure qu'une seule déclaration de service par fichier source.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Stockage en ligne

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

Si vous définissez des règles pour Cloud Firestore et Cloud Storage à l'aide de la CLI Firebase, vous devrez les conserver dans des fichiers séparés.

Correspondre

Un bloc de match déclare un modèle de path qui correspond au chemin de l'opération demandée (le request.path entrant ). Le corps de la match doit avoir un ou plusieurs blocs de match imbriqués, des instructions allow ou function déclarations de function . Le chemin dans les blocs de match imbriqués est relatif au chemin dans le bloc de match parent.

Le modèle de path est un nom de type répertoire qui peut inclure des variables ou des caractères génériques. Le modèle de path permet des correspondances de segment à chemin unique et de segment à chemins multiples. Toutes les variables liées dans un path sont visibles dans la portée de match ou dans toute portée imbriquée où le path est déclaré.

Les correspondances avec un modèle de path peuvent être partielles ou complètes :

  • Correspondances partielles : le modèle de path est une correspondance de préfixe de request.path .
  • Correspondances complètes : le modèle de path correspond à l'intégralité de request.path .

Lorsqu'une correspondance complète est établie, les règles du bloc sont évaluées. Lorsqu'une correspondance partielle est établie, les règles de match imbriquées sont testées pour voir si un path imbriqué terminera la correspondance.

Les règles de chaque match complète sont évaluées pour déterminer s'il faut autoriser la demande. Si une règle de correspondance accorde l'accès, la demande est autorisée. Si aucune règle de correspondance n'accorde l'accès, la demande est refusée.

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

Comme le montre l'exemple ci-dessus, les déclarations de path prennent en charge les variables suivantes :

  • Caractère générique à un seul segment : une variable générique est déclarée dans un chemin en enveloppant une variable entre accolades : {variable} . Cette variable est accessible dans l'instruction match sous forme de string .
  • Caractère générique récursif : le caractère générique récursif, ou multi-segment, correspond à plusieurs segments de chemin au niveau ou au-dessous d'un chemin. Ce caractère générique correspond à tous les chemins situés sous l'emplacement auquel vous l'avez défini. Vous pouvez le déclarer en ajoutant la chaîne =** à la fin de votre variable de segment : {variable=**} . Cette variable est accessible dans l'instruction match tant qu'objet path .

Permettre

Le bloc match contient une ou plusieurs instructions allow . Ce sont vos règles réelles. Vous pouvez appliquer des règles d' allow à une ou plusieurs méthodes. Les conditions d'une instruction allow doivent avoir la valeur true pour que Cloud Firestore ou Cloud Storage accepte toute requête entrante. Vous pouvez également écrire des instructions allow sans conditions, par exemple allow read . Si l'instruction allow n'inclut pas de condition, cependant, elle autorise toujours la requête pour cette méthode.

Si l'une des règles d' allow de la méthode est satisfaite, la demande est autorisée. De plus, si une règle plus large accorde l'accès, les règles accordent l'accès et ignorent les règles plus granulaires qui pourraient limiter l'accès.

Considérez l'exemple suivant, où n'importe quel utilisateur peut lire ou supprimer n'importe lequel de ses propres fichiers. Une règle plus précise n'autorise les écritures que si l'utilisateur qui demande l'écriture possède le fichier et que le fichier est au format PNG. Un utilisateur peut supprimer tous les fichiers du sous-chemin, même s'il ne s'agit pas de fichiers PNG, car la règle précédente le permet.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

Méthode

Chaque instruction allow inclut une méthode qui accorde l'accès aux demandes entrantes de la même méthode.

Méthode Type de demande
Méthodes pratiques
read Tout type de demande de lecture
write Tout type de demande d'écriture
Méthodes standard
get Lire les demandes de documents ou de fichiers uniques
list Lire les demandes de requêtes et de collectes
create Écrire de nouveaux documents ou fichiers
update Écrire dans des documents ou des fichiers existants
delete Suprimmer les données

Vous ne pouvez pas chevaucher des méthodes de lecture dans le même bloc de match ou des méthodes d'écriture en conflit dans la même déclaration de path .

Par exemple, les règles suivantes échoueraient :

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

Une fonction

Au fur et à mesure que vos règles de sécurité deviennent plus complexes, vous souhaiterez peut-être encapsuler des ensembles de conditions dans des fonctions que vous pourrez réutiliser dans votre ensemble de règles. Les règles de sécurité prennent en charge les fonctions personnalisées. La syntaxe des fonctions personnalisées ressemble un peu à JavaScript, mais les fonctions de règles de sécurité sont écrites dans un langage spécifique à un domaine qui présente des limitations importantes :

  • Les fonctions ne peuvent contenir qu'une seule instruction return . Ils 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 variables à partir de la portée dans laquelle elles sont définies. Par exemple, une fonction définie dans la portée du service cloud.firestore a accès à la variable de resource et aux fonctions intégrées telles que get() et exists() .
  • Les fonctions peuvent appeler d'autres fonctions mais ne peuvent pas se reproduire. La profondeur totale de la pile d'appels est limitée à 20.
  • Dans la version v2 règles, les fonctions peuvent définir des variables à l'aide du mot let clé let . Les fonctions peuvent avoir jusqu'à 10 liaisons let, mais doivent se terminer par une instruction return.

Une fonction est définie avec le mot-clé function et prend zéro ou plusieurs arguments. Par exemple, vous pouvez combiner les deux types de conditions utilisées dans les exemples ci-dessus en une seule fonction :

service cloud.firestore {
  match /databases/{database}/documents {
    // 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 /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

Voici un exemple montrant les arguments de fonction et les affectations let. Les instructions d'affectation Let doivent être séparées par des points-virgules.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

Notez comment l'affectation isAdmin applique une recherche de la collection admins. Pour une évaluation paresseuse sans nécessiter de recherches inutiles, profitez de la nature court-circuitante de && (AND) et || (OR) pour appeler une deuxième fonction uniquement si isAuthor est vrai (pour les comparaisons && ) ou faux (pour les comparaisons || ).

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

L'utilisation de fonctions dans vos règles de sécurité les rend plus faciles à gérer à mesure que la complexité de vos règles augmente.

Base de données en temps réel

Comme indiqué ci-dessus, les règles de base de données en temps réel comprennent trois éléments de base : l'emplacement de la base de données en tant que miroir de la structure JSON de la base de données, le type de demande et la condition d'octroi de l'accès.

Emplacement de la base de données

La structure de vos règles doit suivre la structure des données que vous avez stockées dans votre base de données. Par exemple, dans une application de chat avec une liste de messages, vous pourriez avoir des données qui ressemblent à ceci :

  {
    "messages": {
      "message0": {
        "content": "Hello",
        "timestamp": 1405704370369
      },
      "message1": {
        "content": "Goodbye",
        "timestamp": 1405704395231
      },
      ...
    }
  }

Vos règles doivent refléter cette structure. Par example:

  {
    "rules": {
      "messages": {
        "$message": {
          // only messages from the last ten minutes can be read
          ".read": "data.child('timestamp').val() > (now - 600000)",

          // new messages must have a string content and a number timestamp
          ".validate": "newData.hasChildren(['content', 'timestamp']) &&
                        newData.child('content').isString() &&
                        newData.child('timestamp').isNumber()"
        }
      }
    }
  }

Comme le montre l'exemple ci-dessus, les règles de base de données en temps réel prennent en charge une variable $location pour faire correspondre les segments de chemin. Utilisez le préfixe $ devant votre segment de chemin pour faire correspondre votre règle à tous les nœuds enfants le long du chemin.

  {
    "rules": {
      "rooms": {
        // This rule applies to any child of /rooms/, the key for each room id
        // is stored inside $room_id variable for reference
        "$room_id": {
          "topic": {
            // The room's topic can be changed if the room id has "public" in it
            ".write": "$room_id.contains('public')"
          }
        }
      }
    }
  }

Vous pouvez également utiliser la $variable en parallèle avec des noms de chemin constants.

  {
    "rules": {
      "widget": {
        // a widget can have a title or color attribute
        "title": { ".validate": true },
        "color": { ".validate": true },

        // but no other child paths are allowed
        // in this case, $other means any key excluding "title" and "color"
        "$other": { ".validate": false }
      }
    }
  }

Méthode

Dans Realtime Database, il existe trois types de règles. Deux de ces types de règles ( read et write ) s'appliquent à la méthode d'une requête entrante. Le type de règle de validate applique les structures de données et valide le format et le contenu des données. Les règles exécutent les règles .validate après avoir vérifié qu'une règle .write accorde l'accès.

Types de règles
.lis Décrit si et quand les données sont autorisées à être lues par les utilisateurs.
.écrivez Décrit si et quand les données sont autorisées à être écrites.
.valider Définit à quoi ressemblera une valeur correctement formatée, si elle a des attributs enfants et le type de données.

Par défaut, s'il n'y a pas de règle l'autorisant, l'accès à un chemin est refusé.

Conditions de construction

Cloud Firestore

Une condition est une expression booléenne qui détermine si une opération particulière doit être autorisée ou refusée. Les variables de request et de resource fournissent un contexte pour ces conditions.

La variable de request

La variable de request comprend les champs suivants et les informations correspondantes :

request.auth

Un jeton Web JSON (JWT) qui contient les informations d'authentification de Firebase Authentication. auth jeton d' auth contient un ensemble de revendications standard et toutes les revendications personnalisées que vous créez via Firebase Authentication. En savoir plus sur les règles de sécurité et l'authentification Firebase .

request.method

La request.method peut être l'une des méthodes standard ou une méthode personnalisée. Les méthodes pratiques read et write existent également pour simplifier les règles d'écriture qui s'appliquent respectivement à toutes les méthodes standard en lecture seule ou à toutes les méthodes standard en écriture seule.

request.params

Les request.params incluent toutes les données non spécifiquement liées à request.resource qui pourraient être utiles pour l'évaluation. En pratique, cette carte doit être vide pour toutes les méthodes standard et doit contenir des données non-ressources pour les méthodes personnalisées. Les services doivent veiller à ne pas renommer ou modifier le type des clés et des valeurs présentées comme paramètres.

request.path

Le request.path est le chemin de la resource cible. Le chemin est relatif au service. Les segments de chemin contenant des caractères non sécurisés pour les URL tels que / sont codés en URL.

La variable resource

La resource est la valeur actuelle au sein du service représentée sous la forme d'une carte de paires clé-valeur. Le référencement d'une resource dans une condition entraînera au plus une lecture de la valeur à partir du service. Cette recherche sera décomptée de tout quota lié au service pour la ressource. Pour les demandes d' get , la resource ne sera prise en compte que dans le quota en cas de refus.

Opérateurs et priorité des opérateurs

Utilisez le tableau ci-dessous comme référence pour les opérateurs et leur priorité correspondante dans les règles pour Cloud Firestore et Cloud Storage.

Étant donné des expressions arbitraires a et b , un champ f et un indice i .

Opérateur La description L'associativité
a[i] a() af Index, appel, accès au champ de gauche à droite
!a -a Négation unaire de droite à gauche
a/ba%ba*b Opérateurs multiplicatifs de gauche à droite
a+b ab Opérateurs additifs de gauche à droite
a>ba>=ba Opérateurs relationnels de gauche à droite
a in b Existence en liste ou carte de gauche à droite
a is type Comparaison de type, où le type peut être bool, entier, flottant, nombre, chaîne, liste, carte, horodatage, durée, chemin ou latlng de gauche à droite
a==ba!=b Opérateurs de comparaison de gauche à droite
a && b ET conditionnel de gauche à droite
a || b OU conditionnel de gauche à droite
a ? true_value : false_value Expression ternaire de gauche à droite

Stockage en ligne

Une condition est une expression booléenne qui détermine si une opération particulière doit être autorisée ou refusée. Les variables de request et de resource fournissent un contexte pour ces conditions.

La variable de request

La variable de request comprend les champs suivants et les informations correspondantes :

request.auth

Un jeton Web JSON (JWT) qui contient les informations d'authentification de Firebase Authentication. auth jeton d' auth contient un ensemble de revendications standard et toutes les revendications personnalisées que vous créez via Firebase Authentication. En savoir plus sur les règles de sécurité et l'authentification Firebase .

request.method

La request.method peut être l'une des méthodes standard ou une méthode personnalisée. Les méthodes pratiques read et write existent également pour simplifier les règles d'écriture qui s'appliquent respectivement à toutes les méthodes standard en lecture seule ou à toutes les méthodes standard en écriture seule.

request.params

Les request.params incluent toutes les données non spécifiquement liées à request.resource qui pourraient être utiles pour l'évaluation. En pratique, cette carte doit être vide pour toutes les méthodes standard et doit contenir des données non-ressources pour les méthodes personnalisées. Les services doivent veiller à ne pas renommer ou modifier le type des clés et des valeurs présentées comme paramètres.

request.path

Le request.path est le chemin de la resource cible. Le chemin est relatif au service. Les segments de chemin contenant des caractères non sécurisés pour les URL tels que / sont codés en URL.

La variable resource

La resource est la valeur actuelle au sein du service représentée sous la forme d'une carte de paires clé-valeur. Le référencement d'une resource dans une condition entraînera au plus une lecture de la valeur à partir du service. Cette recherche sera décomptée de tout quota lié au service pour la ressource. Pour les demandes d' get , la resource ne sera prise en compte que dans le quota en cas de refus.

Opérateurs et priorité des opérateurs

Utilisez le tableau ci-dessous comme référence pour les opérateurs et leur priorité correspondante dans les règles pour Cloud Firestore et Cloud Storage.

Étant donné des expressions arbitraires a et b , un champ f et un indice i .

Opérateur La description L'associativité
a[i] a() af Index, appel, accès au champ de gauche à droite
!a -a Négation unaire de droite à gauche
a/ba%ba*b Opérateurs multiplicatifs de gauche à droite
a+b ab Opérateurs additifs de gauche à droite
a>ba>=ba Opérateurs relationnels de gauche à droite
a in b Existence en liste ou carte de gauche à droite
a is type Comparaison de type, où le type peut être bool, entier, flottant, nombre, chaîne, liste, carte, horodatage, durée, chemin ou latlng de gauche à droite
a==ba!=b Opérateurs de comparaison de gauche à droite
a && b ET conditionnel de gauche à droite
a || b OU conditionnel de gauche à droite
a ? true_value : false_value Expression ternaire de gauche à droite

Base de données en temps réel

Une condition est une expression booléenne qui détermine si une opération particulière doit être autorisée ou refusée. Vous pouvez définir ces conditions dans les règles de base de données en temps réel des manières suivantes.

Variables prédéfinies

Il existe un certain nombre de variables prédéfinies utiles auxquelles on peut accéder dans une définition de règle. Voici un bref résumé de chacun :

Variables prédéfinies
à présent L'heure actuelle en millisecondes depuis l'époque Linux. Cela fonctionne particulièrement bien pour valider les horodatages créés avec firebase.database.ServerValue.TIMESTAMP du SDK.
racine Un RuleDataSnapshot représentant le chemin racine dans la base de données Firebase tel qu'il existait avant la tentative d'opération.
nouvelles données Un RuleDataSnapshot représentant les données telles qu'elles existeraient après la tentative d'opération. Il comprend les nouvelles données en cours d'écriture et les données existantes.
Les données Un RuleDataSnapshot représentant les données telles qu'elles existaient avant la tentative d'opération.
$ variables Chemin générique utilisé pour représenter les identifiants et les clés enfants dynamiques.
authentification Représente la charge utile du jeton d'un utilisateur authentifié.

Ces variables peuvent être utilisées n'importe où dans vos règles. Par exemple, les règles de sécurité ci-dessous garantissent que les données écrites sur le nœud /foo/ doivent être une chaîne de moins de 100 caractères :

{
  "rules": {
    "foo": {
      // /foo is readable by the world
      ".read": true,

      // /foo is writable by the world
      ".write": true,

      // data written to /foo must be a string less than 100 characters
      ".validate": "newData.isString() && newData.val().length < 100"
    }
  }
}

Règles basées sur les données

Toutes les données de votre base de données peuvent être utilisées dans vos règles. En utilisant les variables prédéfinies root , data et newData , vous pouvez accéder à n'importe quel chemin tel qu'il existerait avant ou après un événement d'écriture.

Considérez cet exemple, qui autorise les opérations d'écriture tant que la valeur du nœud /allow_writes/ est true , que le nœud parent n'a pas d'indicateur readOnly défini et qu'il existe un enfant nommé foo dans les données nouvellement écrites :

".write": "root.child('allow_writes').val() === true &&
          !data.parent().child('readOnly').exists() &&
          newData.child('foo').exists()"

Règles basées sur des requêtes

Bien que vous ne puissiez pas utiliser de règles comme filtres, vous pouvez limiter l'accès à des sous-ensembles de données en utilisant des paramètres de requête dans vos règles. Utilisez la query. expressions dans vos règles pour accorder un accès en lecture ou en écriture en fonction des paramètres de requête.

Par exemple, la règle basée sur une requête suivante utilise des règles de sécurité basées sur l' utilisateur et des règles basées sur une requête pour restreindre l'accès aux données de la collection de baskets aux seuls paniers que l'utilisateur actif possède :

"baskets": {
  ".read": "auth.uid != null &&
            query.orderByChild == 'owner' &&
            query.equalTo == auth.uid" // restrict basket access to owner of basket
}

La requête suivante, qui inclut les paramètres de requête dans la règle, aboutirait :

db.ref("baskets").orderByChild("owner")
                 .equalTo(auth.currentUser.uid)
                 .on("value", cb)                 // Would succeed

Cependant, les requêtes qui n'incluent pas les paramètres dans la règle échoueraient avec une erreur PermissionDenied :

db.ref("baskets").on("value", cb)                 // Would fail with PermissionDenied

Vous pouvez également utiliser des règles basées sur des requêtes pour limiter la quantité de données qu'un client télécharge via des opérations de lecture.

Par exemple, la règle suivante limite l'accès en lecture aux 1 000 premiers résultats d'une requête, par ordre de priorité :

messages: {
  ".read": "query.orderByKey &&
            query.limitToFirst <= 1000"
}

// Example queries:

db.ref("messages").on("value", cb)                // Would fail with PermissionDenied

db.ref("messages").limitToFirst(1000)
                  .on("value", cb)                // Would succeed (default order by key)

La query. suivante query. Les expressions sont disponibles dans les règles de base de données en temps réel.

Expressions de règles basées sur des requêtes
Expression Taper La description
requête.orderByKey
query.orderByPriority
query.orderByValue
booléen True pour les requêtes classées par clé, priorité ou valeur. Faux sinon.
requête.orderByChild chaîne
nul
Utilisez une chaîne pour représenter le chemin relatif vers un nœud enfant. Par exemple, query.orderByChild == "address/zip" . Si la requête n'est pas triée par un nœud enfant, cette valeur est nulle.
requête.startAt
requête.endAt
query.equalTo
chaîne
numéro
booléen
nul
Récupère les limites de la requête en cours d'exécution ou renvoie null s'il n'y a pas de jeu de limites.
query.limitToFirst
query.limitToLast
numéro
nul
Récupère la limite de la requête en cours d'exécution ou renvoie null si aucune limite n'est définie.

Les opérateurs

Les règles de base de données en temps réel prennent en charge un certain nombre d' opérateurs que vous pouvez utiliser pour combiner des variables dans l'instruction de condition. Voir la liste complète des opérateurs dans la documentation de référence .

Créer des conditions

Vos conditions réelles varieront en fonction de l'accès que vous souhaitez accorder. Les règles offrent intentionnellement un degré énorme de flexibilité, de sorte que les règles de votre application peuvent finalement être aussi simples ou aussi complexes que vous le souhaitez.

Pour obtenir des conseils sur la création de règles simples et prêtes pour la production, consultez Règles de sécurité de base .