Règle : Types
.lire
Accorde à un client un accès en lecture à un emplacement de base de données en temps réel Firebase.
Une règle .read
est un type de règle de sécurité qui accorde à un client un accès en lecture à un emplacement de la base de données en temps réel Firebase. Par exemple:
".read": "auth != null && auth.provider == 'twitter'"
La valeur d'une règle .read
est une chaîne, qui est évaluée comme un sous-ensemble de la syntaxe d'expression de JavaScript avec quelques changements de comportement pour augmenter la clarté et l'exactitude. Une règle .read
qui accorde l'autorisation de lire un emplacement permettra également la lecture de tous les descendants de cet emplacement, même si les descendants ont leurs propres règles .read
qui échouent.
Une règle .read
a accès à toutes les variables de règle de la base de données en temps réel Firebase, à l'exception newData
.
.écrire
Accorde à un client un accès en écriture à un emplacement de base de données en temps réel Firebase.
Une règle .write
est un type de règle de sécurité qui accorde à un client un accès en écriture à un emplacement de base de données en temps réel Firebase. Par exemple:
".write": "auth != null && auth.token.isAdmin == true"
La valeur d'une règle .write
est une chaîne, qui est évaluée comme un sous-ensemble de la syntaxe d'expression JavaScript avec quelques changements de comportement pour augmenter la clarté et l'exactitude. Une règle .write
qui accorde l'autorisation d'écrire dans un emplacement permettra également d'écrire sur tous les descendants de cet emplacement, même si les descendants ont leurs propres règles .write
qui échouent.
Une règle .write
a accès à toutes les variables de règle de la base de données en temps réel Firebase.
.valider
Utilisé une fois qu'une règle .write
a accordé l'accès, pour garantir que les données en cours d'écriture sont conformes à un schéma spécifique.
Une règle .validate
est utilisée une fois qu'une règle .write
a accordé l'accès, pour garantir que les données en cours d'écriture sont conformes à une norme spécifique. En plus d'un accès .write
accordant, toutes les règles .validate
pertinentes doivent réussir avant qu'une écriture ne soit autorisée. Par exemple:
".validate": "newData.hasChildren(['name', 'age'])"
La valeur d'une règle .validate
est une chaîne, qui est évaluée comme un sous-ensemble de la syntaxe d'expression de JavaScript avec quelques changements de comportement pour augmenter la clarté et l'exactitude.
Une règle .validate
a accès à toutes les variables de règle de la base de données en temps réel Firebase.
.indexOn
Améliore les performances des requêtes en indiquant à la base de données Firebase Realtime les clés sur lesquelles vous souhaitez que vos données soient indexées.
La règle .indexOn
indique aux serveurs de base de données Firebase Realtime d'indexer des clés spécifiques dans vos données pour améliorer les performances de vos requêtes. Par exemple, étant donné une base de données contenant une collection de données sur les dinosaures, nous pouvons demander à Firebase Realtime Database d'optimiser les requêtes, avant qu'elles ne soient renvoyées par les serveurs, en ajoutant cette règle :
{
"rules": {
"dinosaurs": {
".indexOn": ["height", "length"]
}
}
}
Vous pouvez trouver plus d'informations sur la règle .indexOn
en vous référant à la section du guide de sécurité sur l'indexation de vos données .
Règle : Variables
authentification
Une variable contenant la charge utile du jeton si un client est authentifié, ou null
si le client n'est pas authentifié.
Firebase Realtime Database vous permet de vous authentifier facilement auprès de plusieurs fournisseurs intégrés et générera des jetons d'authentification pour eux. Une fois qu'un utilisateur est authentifié auprès de l'un des fournisseurs intégrés, la variable auth contiendra les éléments suivants :
Champ | Description |
---|---|
provider | La méthode d'authentification utilisée (par exemple "mot de passe", "anonyme", "facebook", "github", "google" ou "twitter"). |
uid | Un identifiant utilisateur unique, garanti unique pour tous les fournisseurs. |
token | Le contenu du jeton d'identification d'authentification Firebase. Voir auth.token . |
À titre d'exemple, nous pourrions avoir une règle comme celle-ci pour permettre aux utilisateurs de créer des commentaires à condition qu'ils stockent leur identifiant utilisateur avec le commentaire :
{
"rules": {
".read": true,
"$comment": {
".write": "!data.exists() && newData.child('user_id').val() == auth.uid"
}
}
}
Nous pourrions également établir une règle comme celle-ci pour permettre aux utilisateurs de créer des commentaires tant qu'ils sont connectés via Facebook :
{
"rules": {
".read": true,
"$comment": {
".write": "!data.exists() && auth.provider == 'facebook'"
}
}
}
jeton d'authentification
Une variable contenant le contenu du jeton d'identification d'authentification Firebase.
Le jeton contient tout ou partie des clés suivantes :
Champ | Description |
---|---|
email | L'adresse e-mail associée au compte, si présente. |
email_verified | true si l'utilisateur a vérifié qu'il a accès à l'adresse email . Certains fournisseurs vérifient automatiquement les adresses e-mail dont ils sont propriétaires. |
phone_number | Le numéro de téléphone associé au compte, s'il est présent. |
name | Le nom d’affichage de l’utilisateur, s’il est défini. |
sub | L'UID Firebase de l'utilisateur. C’est unique dans un projet. |
firebase.identities | Dictionnaire de toutes les identités associées au compte de cet utilisateur. Les clés du dictionnaire peuvent être les suivantes : email , phone , google.com , facebook.com , github.com , twitter.com . Les valeurs du dictionnaire sont des tableaux d'identifiants uniques pour chaque fournisseur d'identité associé au compte. Par exemple, auth.token.firebase.identities["google.com"][0] contient le premier identifiant Google associé au compte. |
firebase.sign_in_provider | Fournisseur de connexion utilisé pour obtenir ce jeton. Il peut s'agir de l'une des chaînes suivantes : custom , password , phone , anonymous , google.com , facebook.com , github.com , twitter.com . |
firebase.tenant | Le tenantId associé au compte, s'il est présent. par exemple tenant2-m6tyz |
Si vous utilisez une authentification personnalisée, auth.token
contient également toutes les revendications personnalisées spécifiées par le développeur.
Toutes ces valeurs peuvent être utilisées dans les règles. Par exemple, pour restreindre l'accès aux comptes Google associés à une adresse gmail.com, on pourrait ajouter la règle :
{
"rules": {
".read": "auth != null",
"gmailUsers": {
"$uid": {
".write": "auth.token.email_verified == true && auth.token.email.matches(/.*@gmail.com$/)"
}
}
}
}
Par souci d'exhaustivité, les champs suivants sont également inclus dans auth.token
, mais il est peu probable qu'ils soient utiles pour les règles.
Champ | Description |
---|---|
iss | L'émetteur du jeton. |
aud | Le public du jeton. |
auth_time | La dernière fois que l'utilisateur s'est authentifié avec un identifiant à l'aide de l'appareil recevant le jeton. |
iat | L'heure à laquelle le jeton a été émis. |
exp | L'heure à laquelle le jeton expire. |
$emplacement
Une variable qui peut être utilisée pour référencer la clé d'un $location
qui a été utilisée précédemment dans une structure de règles.
Lorsque vous avez un $location
dans votre structure de règles, vous pouvez utiliser une variable $
correspondante dans votre expression de règle pour obtenir le nom de l'enfant réel en cours de lecture ou d'écriture. Supposons donc que nous voulions donner à chaque utilisateur un accès en lecture et en écriture à son propre emplacement /users/<user>
. Nous pourrions utiliser :
{
"rules": {
"users": {
"$user": {
".read": "auth.uid === $user",
".write": "auth.uid === $user"
}
}
}
}
Lorsqu'un client tente d'accéder à /users/barney
, l'emplacement par défaut $user
correspondra à $user
étant égal à "barney". Ainsi, la règle .read
vérifiera si auth.uid === 'barney'
. Par conséquent, la lecture de
ne réussira que si le client est authentifié avec un uid « barney »./users/barney
maintenant
Contient le nombre de millisecondes depuis l'époque Unix selon les serveurs Firebase Realtime Database.
La variable now
contient le nombre de millisecondes depuis l'époque UNIX selon les serveurs Firebase Realtime Database. Par exemple, vous pouvez utiliser ceci pour vérifier que l'heure created
d'un utilisateur n'est jamais définie sur une heure future :
{
"rules": {
"users": {
"$user": {
"created": {
".validate": "newData.val() < now"
}
}
}
}
}
racine
Un RuleDataSnapshot correspondant aux données actuelles à la racine de votre base de données Firebase Realtime.
La variable racine vous donne un RuleDataSnapshot correspondant aux données actuelles à la racine de votre base de données Firebase Realtime. Vous pouvez l'utiliser pour lire toutes les données de votre base de données dans vos expressions de règle. Par exemple, si nous voulions permettre aux utilisateurs de lire /comments
uniquement si leur /users/<id>/active
était défini sur true, nous pourrions utiliser :
{
"rules": {
"comments": {
".read": "root.child('users').child(auth.uid).child('active').val() == true"
}
}
}
Ensuite, si /users/barney/active
contenait la valeur true, un utilisateur authentifié avec un uid de « barney » pourrait écrire sur le nœud /comments
.
données
Un RuleDataSnapshot correspondant aux données actuelles dans la base de données Firebase Realtime à l'emplacement de la règle en cours d'exécution.
La variable data vous donne un RuleDataSnapshot correspondant aux données actuelles dans l'emplacement de la base de données de la règle en cours d'exécution (par opposition à root, qui vous donne les données pour la racine de votre base de données).
Ainsi, par exemple, si vous souhaitez permettre à n'importe quel client d'accéder à /users/<user>
si /users/<user>/public
est défini sur true, vous pouvez utiliser :
{
"rules": {
"users": {
"$user": {
".read": "data.child('public').val() == true"
}
}
}
}
La variable data est disponible dans les règles .read
, .write
et .validate
.
nouvelles données
Un RuleDataSnapshot correspondant aux données qui résulteront si l'écriture est autorisée.
Pour les règles .write
et .validate
, la variable newData vous donne un RuleDataSnapshot correspondant aux données qui résulteront si l'écriture est autorisée (il s'agit d'une "fusion" des données existantes plus les nouvelles données en cours d'écriture). Donc, si vous voulez vous assurer que chaque utilisateur a un nom et un âge, vous pouvez utiliser :
{
"rules": {
"users": {
"$user": {
".read": true,
".write": true,
".validate": "newData.hasChildren(['name', 'age'])"
}
}
}
}
Puisque newData fusionne les données existantes et les nouvelles données, il se comporte correctement même pour les mises à jour « partielles ». Par exemple:
var fredRef = firebase.database().ref("users/fred");
// Valid since we have a name and age.
fredRef.set({ name: "Fred", age: 19 });
// Valid since we are updating the name but there's already an age.
fredRef.child("age").set(27);
// Invalid since the .validate rule will no longer be true.
fredRef.child("name").remove();
La variable newData n'est pas disponible dans les règles .read
car aucune nouvelle donnée n'est écrite. Vous devriez simplement utiliser data .
RuleDataSnapshot : méthodes
val()
Obtient la valeur primitive ( string
, number
, boolean
ou null
) de ce RuleDataSnapshot .
Valeur de retour : ( String
, Number
, Boolean
, Null
) - La valeur primitive de ce RuleDataSnapshot .
Contrairement à DataSnapshot.val()
, l'appel val()
sur un RuleDataSnapshot contenant des données enfants ne renverra pas d'objet contenant les enfants. Il renverra à la place une valeur sentinelle spéciale. Cela garantit que les règles peuvent toujours fonctionner de manière extrêmement efficace.
Par conséquent, vous devez toujours utiliser child()
pour accéder aux enfants (par exemple data.child('name').val()
, pas data.val().name
).
Cet exemple autorise la lecture uniquement si l'enfant isReadable est défini sur true à l'emplacement en cours de lecture.
".read": "data.child('isReadable').val() == true"
enfant()
Obtient un RuleDataSnapshot pour l'emplacement au chemin relatif spécifié.
Arguments : childPath
String
- Un chemin relatif vers l'emplacement des données enfants.
Valeur de retour : RuleDataSnapshot
- Le RuleDataSnapshot pour l'emplacement enfant.
Le chemin relatif peut être soit un simple nom d'enfant (par exemple 'fred') ou un chemin plus profond séparé par des barres obliques (par exemple 'fred/nom/premier'). Si l'emplacement enfant ne contient aucune donnée, un RuleDataSnapshot vide est renvoyé.
Cet exemple autorise la lecture uniquement si l'enfant isReadable est défini sur true à l'emplacement en cours de lecture.
".read": "data.child('isReadable').val() == true"
parent()
Obtient un RuleDataSnapshot pour l'emplacement parent.
Valeur de retour : RuleDataSnapshot
- Le RuleDataSnapshot pour l'emplacement parent.
Si cette instance fait référence à la racine de votre base de données Firebase Realtime, elle n'a pas de parent et parent()
échouera, entraînant l'omission de l'expression de règle actuelle (comme un échec).
Cet exemple autorise la lecture uniquement si le frère isReadable est défini sur true.
".read": "data.parent().child('isReadable').val() == true"
hasChild (chemin enfant)
Renvoie vrai si l'enfant spécifié existe.
Arguments : childPath
String
- Un chemin relatif vers l'emplacement d'un enfant potentiel.
Valeur de retour : Booléen - true
si les données existent sur le chemin enfant spécifié ; sinon false
.
Cet exemple permet uniquement d'écrire les données si elles contiennent un "nom" enfant.
".validate": "newData.hasChild('name')"
aEnfants([enfants])
Vérifie l'existence des enfants.
Arguments : children
Array
facultatif - Un tableau de clés enfants qui doivent toutes exister.
Valeur de retour : Boolean
- true
si les enfants (spécifiés) existent ; sinon false
.
Si aucun argument n'est fourni, il retournera vrai si RuleDataSnapshot a des enfants. Si un tableau de noms d'enfants est fourni, il renverra true uniquement si tous les enfants spécifiés existent dans RuleDataSnapshot .
Cet exemple permet uniquement d'écrire les données si elles contiennent un ou plusieurs enfants.
".validate": "newData.hasChildren()"
Cet exemple permet uniquement d'écrire les données si elles contiennent des enfants "nom" et "âge".
".validate": "newData.hasChildren(['name', 'age'])"
existe()
Renvoie vrai si ce RuleDataSnapshot contient des données.
Valeur de retour : Boolean
- true
si RuleDataSnapshot contient des données ; sinon false
.
La fonction exist renvoie true si ce RuleDataSnapshot contient des données. Il s'agit simplement d'une fonction pratique puisque data.exists()
est équivalent à data.val() != null
.
Cet exemple autorise une écriture à cet emplacement tant qu'il n'y a pas de données existantes.
".write": "!data.exists()"
obtenirPriorité()
Obtient la priorité des données dans un RuleDataSnapshot .
Valeur de retour : ( String
, Number
, Null
) - La priorité des données dans ce RuleDataSnapshot .
Cet exemple garantit que les nouvelles données en cours d'écriture ont une priorité
".validate": "newData.getPriority() != null"
estNuméro()
Renvoie vrai si ce RuleDataSnapshot contient une valeur numérique.
Valeur de retour : Boolean
- true
si les données sont numériques ; sinon false
.
Cet exemple garantit que les nouvelles données en cours d'écriture ont un "âge" enfant avec une valeur numérique.
".validate": "newData.child('age').isNumber()"
estString()
Renvoie vrai si ce RuleDataSnapshot contient une valeur de chaîne.
Valeur de retour : Boolean
- true
si les données sont une String
; sinon false
.
Cet exemple garantit que les nouvelles données en cours d'écriture ont un « nom » enfant avec une valeur de chaîne.
".validate": "newData.child('name').isString()
estBooléen()
Renvoie vrai si ce RuleDataSnapshot contient une valeur booléenne.
Valeur de retour : Boolean
- true
si les données sont Boolean
; sinon false
.
Cet exemple garantit que les nouvelles données en cours d'écriture ont un enfant « actif » avec une valeur booléenne.
".validate": "newData.child('active').isBoolean()"
Chaîne : Propriétés
longueur
Renvoie la longueur de la chaîne.
Valeur de retour : Number
- Le nombre de caractères dans la chaîne.
Cet exemple nécessite que la chaîne comporte au moins 10 caractères.
".validate": "newData.isString() && newData.val().length >= 10"
Chaîne : méthodes
contient (sous-chaîne)
Renvoie vrai si la chaîne contient la sous-chaîne spécifiée.
Arguments : substring
String
- Une sous-chaîne à rechercher.
Valeur de retour : Boolean
- true
si la chaîne contient la sous-chaîne spécifiée ; sinon false
.
Cet exemple nécessite que les données soient une chaîne contenant « @ ».
".validate": "newData.isString() && newData.val().contains('@')"
commenceAvec(sous-chaîne)
Renvoie vrai si la chaîne commence par la sous-chaîne spécifiée.
Arguments : substring
String
- Une sous-chaîne à rechercher au début.
Valeur de retour : Boolean
- true
si la chaîne contient la sous-chaîne spécifiée ; sinon false
.
Cet exemple autorise l'accès en lecture si auth.token.identifier
commence par "interne-"
".read": "auth.token.identifier.beginsWith('internal-')"
se termine par (sous-chaîne)
Renvoie vrai si la chaîne se termine par la sous-chaîne spécifiée.
Arguments : substring
String
- Une sous-chaîne à rechercher à la fin.
Valeur de retour : Boolean
- true
si la chaîne se termine par la sous-chaîne spécifiée ; sinon false
.
Cet exemple autorise l'accès en lecture si auth.token.identifier
se termine par "@company.com"
".read": "auth.token.identifier.endsWith('@company.com')"
remplacer (sous-chaîne, remplacement)
Renvoie une copie de la chaîne avec toutes les instances d'une sous-chaîne spécifiée remplacées par la chaîne de remplacement spécifiée.
Arguments : substring String
- Une sous-chaîne à rechercher. replacement String
- Une chaîne par laquelle remplacer la sous-chaîne.
Valeur de retour : String
- La nouvelle chaîne après avoir remplacé la sous-chaîne par le remplacement.
La méthode replace()
diffère légèrement de la méthode JavaScript replace()
dans la mesure où elle remplace toutes les instances d'une sous-chaîne spécifiée par la chaîne de remplacement spécifiée, et pas seulement la première instance.
Étant donné que les points ne sont pas autorisés dans les clés, nous devons échapper les chaînes avec des points avant de les stocker. Un exemple de ceci serait avec les adresses e-mail. Supposons que nous ayons une liste d'adresses e-mail sur liste blanche dans notre nœud /whitelist/
:
{
"user": {
"$uid": {
"email": <email>
}
},
"whitelist": {
"fred@gmail%2Ecom": true,
"barney@aol%2Ecom": true
}
}
Nous pouvons créer une règle qui autorise l'ajout d'utilisateurs uniquement si leur adresse e-mail se trouve dans le nœud /whitelist/
:
{
"rules": {
"users": {
"$uid": {
".read": "true",
".write": "root.child('whitelist').child(newData.child('email').val().replace('.', '%2E')).exists()"
}
}
}
}
versMinuscule()
Renvoie une copie de la chaîne convertie en minuscules.
Valeur de retour : String
- La chaîne convertie en minuscules.
Cet exemple permet l'accès en lecture si auth.token.identifier
car toutes les minuscules existent sous /users
.
".read": "root.child('users').child(auth.token.identifier.toLowerCase()).exists()"
versUpperCase()
Renvoie une copie de la chaîne convertie en majuscules.
Valeur de retour : String
- La chaîne convertie en majuscules.
Cet exemple permet l'accès en lecture si auth.token.identifier
car toutes les majuscules existent sous /users
.
".read": "root.child('users').child(auth.token.identifier.toUpperCase()).exists()"
correspondances (regex)
Renvoie vrai si la chaîne correspond au littéral d’expression régulière spécifié.
Valeur de retour : Boolean
- true
si la chaîne correspond au littéral de l'expression régulière, regex ; sinon false
.
Voir la documentation complète des règles regex .
Les opérateurs
+ (ajouter)
Utilisé pour ajouter des variables ou pour la concaténation de chaînes.
L'exemple suivant garantit que la nouvelle valeur incrémente la valeur existante d'exactement une. Ceci est utile pour implémenter un compteur :
".write": "newData.val() === data.val() + 1"
".validate": "root.child('room_names/' + $room_id).exists()"
- (annuler ou soustraire)
Utilisé pour annuler une valeur ou soustraire deux valeurs dans une expression de règles.
Cette règle de validation vérifie que la nouvelle valeur est l'inverse d'une valeur enfant à l'emplacement :
".validate": "newData.val() === -(data.child('quantity').val())"
L'exemple suivant utilise la soustraction pour garantir que seuls les messages des dix dernières minutes peuvent être lus :
".read": "newData.child('timestamp').val() > (now - 600000)"
* (multiplier)
Utilisé pour multiplier des variables dans une expression de règles.
Cette règle de validation vérifie si la nouvelle valeur est égale au produit en prix et en quantité (deux valeurs existantes) :
".validate": "newData.val() === data.child('price').val() * data.child('quantity').val()"
/ (diviser)
Utilisé pour diviser des variables dans une expression de règles.
Dans l'exemple suivant, la règle de validation garantit que les données stockées correspondent à la moyenne du total des données stockées ailleurs :
".validate": "newData.val() === data.parent().child('sum').val() / data.parent().child('numItems').val()"
% (module)
Utilisé pour trouver le reste de la division d'une variable par une autre dans une expression de règles.
Cette règle valide que seuls les nombres pairs peuvent être écrits :
".validate": "newData.val() % 2 === 0"
=== (égal)
Utilisé pour vérifier si deux variables dans une expression de règles ont le même type et la même valeur.
La règle suivante utilise l'opérateur === pour accorder l'accès en écriture uniquement au propriétaire du compte utilisateur. L'uid de l'utilisateur doit correspondre exactement à la clé ( $user_id
) pour que la règle soit évaluée comme vraie.
"users": {
".write": "$user_id === auth.uid"
}
!== (pas égal)
Utilisé pour vérifier si deux variables dans une expression de règles ne sont pas égales.
La règle de lecture suivante garantit que seuls les utilisateurs connectés peuvent lire les données :
".read": "auth !== null"
&& (ET)
Prend la valeur true si les deux opérandes sont vrais. Utilisé pour évaluer plusieurs conditions dans une expression de règles.
La règle de validation suivante vérifie que les nouvelles données sont une chaîne de moins de 100 caractères :
".validate": "newData.isString() && newData.val().length < 100"
|| (OU)
Prend la valeur true si un opérande de l'expression de règles est vrai.
Dans cet exemple, nous pouvons écrire tant qu’il n’existe pas d’anciennes données ou de nouvelles données. En d’autres termes, nous pouvons écrire si nous supprimons ou créons des données, mais pas si nous mettons à jour des données.
".write": "!data.exists() || !newData.exists()"
! (PAS)
Prend la valeur true si son seul opérande est faux. Dans les expressions de règles, le ! L'opérateur est souvent utilisé pour voir si des données ont été écrites à un emplacement.
La règle suivante autorise l'accès en écriture uniquement s'il n'y a aucune donnée à l'emplacement spécifié :
".write": "!data.exists()"
> (supérieur à)
Utilisé pour vérifier si une valeur est supérieure à une autre valeur dans une expression de règles.
Cette règle de validation vérifie que la chaîne en cours d'écriture n'est pas une chaîne vide :
".validate": "newData.isString() && newData.val().length > 0"
< (Inférieur à)
Utilisé pour vérifier si une valeur est inférieure à une autre valeur dans une expression de règles.
Cette règle de validation vérifie qu'une chaîne comporte moins de 20 caractères :
".validate": "newData.isString() && newData.val().length < 20"
>= (supérieur ou égal à)
Utilisé pour vérifier si une valeur est supérieure ou égale à une autre valeur dans une expression de règles.
Cette règle de validation vérifie que la chaîne en cours d'écriture n'est pas une chaîne vide :
".validate": "newData.isString() && newData.val().length >= 1"
<= (inférieur ou égal à)
Utilisé pour vérifier si une valeur est inférieure ou égale à une autre valeur dans une expression de règles.
Cette règle de validation garantit que de nouvelles données ne pourront pas être ajoutées à l'avenir :
".validate": "newData.val() <= now"
? (opérateur ternaire)
Utilisé pour évaluer une expression de règles conditionnelles.
L'opérateur ternaire prend trois opérandes. L'opérande avant le ? est la condition. Si la condition est vraie, le deuxième opérande est évalué. Si la condition est fausse, le troisième opérande est évalué.
Pour la règle de validation suivante, la nouvelle valeur peut être un nombre ou un booléen. Si c'est un nombre, il doit être supérieur à 0.
".validate": "newData.isNumber() ? newData.val() > 0 : newData.isBoolean()"