Vous pouvez utiliser Firebase Security Rules pour écrire de nouvelles données de manière conditionnelle en fonction de données existantes dans votre base de données ou votre bucket de stockage. Vous pouvez également écrire des règles qui appliquent de validation en limitant les écritures en fonction des nouvelles données en cours d'écriture. Lire la suite pour en savoir plus sur les règles qui créent des conditions de sécurité à l'aide de données existantes.
Sélectionnez un produit dans chaque section pour en savoir plus sur les règles de validation des données.
Restrictions concernant les nouvelles données
Cloud Firestore
Si vous souhaitez vous assurer qu'un document contenant un champ spécifique n'est pas créé, vous pouvez inclure le champ dans la condition allow
. Par exemple, si
vous souhaitez refuser la création de documents contenant le champ ranking
,
vous l'interdisez dans la condition create
.
service cloud.firestore {
match /databases/{database}/documents {
// Disallow
match /cities/{city} {
allow create: if !("ranking" in request.resource.data)
}
}
}
Realtime Database
Si vous souhaitez vous assurer que les données contenant certaines valeurs ne sont pas ajoutées
à votre base de données, vous devez inclure cette valeur dans vos règles et l'interdire
les opérations d'écriture. Par exemple, si vous souhaitez refuser toutes les écritures contenant ranking
, vous interdisez l'écriture pour les documents avec des valeurs ranking
.
{
"rules": {
// Write is allowed for all paths
".write": true,
// Allows writes only if new data doesn't include a `ranking` child value
".validate": "!newData.hasChild('ranking')
}
}
Cloud Storage
Si vous voulez vous assurer qu'un fichier contenant
des métadonnées spécifiques n'est pas
vous pouvez inclure les métadonnées dans la condition allow
. Par exemple, si
vous souhaitez refuser la création de fichiers contenant des métadonnées ranking
,
vous l'interdisez dans la condition create
.
service firebase.storage {
match /b/{bucket}/o {
match /files/{allFiles=**} {
// Disallow
allow create: if !("ranking" in request.resource.metadata)
}
}
}
Utiliser les données existantes dans Firebase Security Rules
Cloud Firestore
De nombreuses applications stockent des informations de contrôle des accès sous forme de champs dans les documents de la base de données. Cloud Firestore Security Rules peut autoriser ou refuser l'accès de manière dynamique en fonction du document données:
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to read data if the document has the 'visibility'
// field set to 'public'
match /cities/{city} {
allow read: if resource.data.visibility == 'public';
}
}
}
La variable resource
fait référence au document demandé et resource.data
correspond à une carte de tous les champs et valeurs stockés dans le document. Pour plus d'informations sur la variable resource
, consultez la documentation de référence.
Lorsque vous écrivez des données, vous pouvez comparer les données entrantes aux données existantes. Ce
vous permet, par exemple, de vous assurer qu'un champ n'a pas été modifié, qu'un champ n'a
incrémentée de un, ou que la nouvelle valeur soit postérieure d'au moins une semaine à la date du jour.
Dans ce cas, si votre ensemble de règles autorise l'écriture en attente, la variable request.resource
contient l'état futur du document. Pour les opérations update
qui ne modifient qu'un sous-ensemble de champs du document, la variable request.resource
contient l'état du document en attente après l'opération. Vous pouvez vérifier les valeurs des champs dans request.resource
pour éviter les mises à jour de données non souhaitées ou incohérentes :
service cloud.firestore {
match /databases/{database}/documents {
// Make sure all cities have a positive population and
// the name is not changed
match /cities/{city} {
allow update: if request.resource.data.population > 0
&& request.resource.data.name == resource.data.name;
}
}
}
Realtime Database
Dans Realtime Database, utilisez les règles .validate
pour appliquer les structures de données et valider les données.
le format et le contenu des données. Rules exécutent .validate
règles après
en vérifiant qu'une règle .write
accorde l'accès.
Les règles .validate
ne sont pas appliquées en cascade. Si une règle de validation échoue sur une
chemin d'accès ou sous-chemin d'accès de la règle, toute l'opération d'écriture sera rejetée.
De plus, les définitions de validation ne vérifient que les valeurs non nulles.
ignorera ensuite toutes les requêtes
de suppression de données.
Examinez les règles .validate
suivantes:
{
"rules": {
// write is allowed for all paths
".write": true,
"widget": {
// a valid widget must have attributes "color" and "size"
// allows deleting widgets (since .validate is not applied to delete rules)
".validate": "newData.hasChildren(['color', 'size'])",
"size": {
// the value of "size" must be a number between 0 and 99
".validate": "newData.isNumber() &&
newData.val() >= 0 &&
newData.val() <= 99"
},
"color": {
// the value of "color" must exist as a key in our mythical
// /valid_colors/ index
".validate": "root.child('valid_colors/' + newData.val()).exists()"
}
}
}
}
Les requêtes d'écriture dans une base de données avec les règles ci-dessus présenteraient le code suivant : résultats:
JavaScript
var ref = db.ref("/widget"); // PERMISSION_DENIED: does not have children color and size ref.set('foo'); // PERMISSION DENIED: does not have child color ref.set({size: 22}); // PERMISSION_DENIED: size is not a number ref.set({ size: 'foo', color: 'red' }); // SUCCESS (assuming 'blue' appears in our colors list) ref.set({ size: 21, color: 'blue'}); // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child('size').set(99);
Objective-C
FIRDatabaseReference *ref = [[[FIRDatabase database] reference] child: @"widget"]; // PERMISSION_DENIED: does not have children color and size [ref setValue: @"foo"]; // PERMISSION DENIED: does not have child color [ref setValue: @{ @"size": @"foo" }]; // PERMISSION_DENIED: size is not a number [ref setValue: @{ @"size": @"foo", @"color": @"red" }]; // SUCCESS (assuming 'blue' appears in our colors list) [ref setValue: @{ @"size": @21, @"color": @"blue" }]; // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate [[ref child:@"size"] setValue: @99];
Swift
var ref = FIRDatabase.database().reference().child("widget") // PERMISSION_DENIED: does not have children color and size ref.setValue("foo") // PERMISSION DENIED: does not have child color ref.setValue(["size": "foo"]) // PERMISSION_DENIED: size is not a number ref.setValue(["size": "foo", "color": "red"]) // SUCCESS (assuming 'blue' appears in our colors list) ref.setValue(["size": 21, "color": "blue"]) // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child("size").setValue(99);
Java
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("widget"); // PERMISSION_DENIED: does not have children color and size ref.setValue("foo"); // PERMISSION DENIED: does not have child color ref.child("size").setValue(22); // PERMISSION_DENIED: size is not a number Map<String,Object> map = new HashMap<String, Object>(); map.put("size","foo"); map.put("color","red"); ref.setValue(map); // SUCCESS (assuming 'blue' appears in our colors list) map = new HashMap<String, Object>(); map.put("size", 21); map.put("color","blue"); ref.setValue(map); // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child("size").setValue(99);
REST
# PERMISSION_DENIED: does not have children color and size curl -X PUT -d 'foo' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # PERMISSION DENIED: does not have child color curl -X PUT -d '{"size": 22}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # PERMISSION_DENIED: size is not a number curl -X PUT -d '{"size": "foo", "color": "red"}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # SUCCESS (assuming 'blue' appears in our colors list) curl -X PUT -d '{"size": 21, "color": "blue"}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # If the record already exists and has a color, this will # succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) # will fail to validate curl -X PUT -d '99' \ https://docs-examples.firebaseio.com/rest/securing-data/example/size.json
Cloud Storage
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.
L'objet resource
contient des paires clé/valeur avec des métadonnées de fichier affichées dans un
Cloud Storage. Ces propriétés peuvent être inspectées sur read
ou
write
pour garantir l'intégrité des données. L'objet resource
vérifie les métadonnées des fichiers existants dans votre bucket Cloud Storage.
service firebase.storage {
match /b/{bucket}/o {
match /images {
match /{allImages=**} {
// Allow reads if a custom 'visibility' field is set to 'public'
allow read: if resource.metadata.visibility == 'public';
}
}
}
}
Vous pouvez également utiliser l'objet request.resource
avec les requêtes write
(comme
les importations, les mises à jour
de métadonnées et les suppressions. L'objet request.resource
est obtenu
métadonnées du fichier qui seront écrites si write
est autorisé.
Vous pouvez utiliser ces deux valeurs pour éviter les mises à jour indésirables ou incohérentes ou pour appliquer des contraintes d'application, telles que le type ou la taille du fichier.
service firebase.storage {
match /b/{bucket}/o {
match /images {
// Cascade read to any image type at any path
match /{allImages=**} {
allow read;
}
// Allow write files to the path "images/*", subject to the constraints:
// 1) File is less than 5MB
// 2) Content type is an image
// 3) Uploaded content type matches existing content type
// 4) File name (stored in imageId wildcard variable) is less than 32 characters
match /{imageId} {
allow write: if request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*')
&& request.resource.contentType == resource.contentType
&& imageId.size() < 32
}
}
}
}
La liste complète des propriétés de l'objet resource
est disponible dans
documentation de référence.