Puoi utilizzare Firebase Security Rules per scrivere in modo condizionale nuovi dati in base a quelli esistenti nel database o nel bucket di archiviazione. Puoi anche scrivere regole che applicano la convalida dei dati limitando le scritture in base ai nuovi dati scritti. Continua a leggere per scoprire di più sulle regole che utilizzano i dati esistenti per creare condizioni di sicurezza.
Seleziona un prodotto in ogni sezione per scoprire di più sulle regole di convalida dei dati.
Limitazioni per i nuovi dati
Cloud Firestore
Se vuoi assicurarti che non venga creato un documento che contiene un campo specifico, puoi includere il campo nella condizione allow
. Ad esempio, se
vuoi negare la creazione di documenti che contengono il campo ranking
,
devi disattivarla nella condizione create
.
service cloud.firestore {
match /databases/{database}/documents {
// Disallow
match /cities/{city} {
allow create: if !("ranking" in request.resource.data)
}
}
}
Realtime Database
Se vuoi assicurarti che i dati che contengono determinati valori non vengano aggiunti
al tuo database, includi quel valore nelle regole e non consentirne
la scrittura. Ad esempio, se vuoi negare qualsiasi scrittura che contenga valori ranking
, non consentirai le scritture per qualsiasi documento con valori 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
Se vuoi assicurarti che non venga creato un file che contiene metadati specifici, puoi includerli nella condizione allow
. Ad esempio, se vuoi negare la creazione di file che contengono metadati ranking
, devi vietarla nella condizione create
.
service firebase.storage {
match /b/{bucket}/o {
match /files/{fileName} {
// Disallow
allow create: if !("ranking" in request.resource.metadata)
}
}
}
Utilizzare i dati esistenti in Firebase Security Rules
Cloud Firestore
Molte app archiviano le informazioni sul controllo dell'accesso come campi nei documenti del database. Cloud Firestore Security Rules può consentire o negare dinamicamente l'accesso in base ai dati del documento:
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 variabile resource
si riferisce al documento richiesto e resource.data
è
una mappa di tutti i campi e i valori archiviati nel documento. Per ulteriori
informazioni sulla variabile resource
, consulta la documentazione
di riferimento.
Quando scrivi i dati, potresti voler confrontare i dati in entrata con quelli esistenti. In questo modo
puoi assicurarti, ad esempio, che un campo non sia stato modificato, che un campo sia stato incrementato
di una sola unità o che il nuovo valore sia almeno una settimana nel futuro.
In questo caso, se il ruleset consente la scrittura in attesa, la variabile request.resource
contiene lo stato futuro del documento. Per le operazioni update
che modificano solo un sottoinsieme dei campi del documento, la variabile request.resource
conterrà lo stato del documento in attesa dopo l'operazione. Puoi controllare i valori dei campi in request.resource
per evitare aggiornamenti dei dati indesiderati o incoerenti:
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
In Realtime Database, utilizza le regole .validate
per applicare le strutture dei dati e convalidare
il formato e i contenuti dei dati. Rules esegui le regole .validate
dopo aver verificato che una regola .write
conceda l'accesso.
Le regole .validate
non vengono applicate in cascata. Se una regola di convalida non viene superata per qualsiasi
percorso o sottopercorso della regola, l'intera operazione di scrittura verrà rifiutata.
Inoltre, la convalida delle definizioni controlla solo i valori non nulli e
successivamente ignora tutte le richieste che eliminano i dati.
Considera le seguenti regole .validate
:
{
"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()"
}
}
}
}
Le richieste di scrittura a un database con le regole sopra indicate avrebbero i seguenti risultati:
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
Quando valuti le regole, potresti anche voler valutare i metadati del file che viene caricato, scaricato, modificato o eliminato. In questo modo puoi creare regole complesse e potenti che consentono, ad esempio, di caricare solo file con determinati tipi di contenuti o di eliminare solo file di dimensioni superiori a una determinata soglia.
L'oggetto resource
contiene coppie chiave-valore con i metadati del file visualizzati in un
oggetto Cloud Storage. Queste proprietà possono essere esaminate nelle richieste read
o
write
per garantire l'integrità dei dati. L'oggetto resource
controlla i metadati
dei file esistenti nel bucket Cloud Storage.
service firebase.storage {
match /b/{bucket}/o {
match /images {
match /{fileName} {
// Allow reads if a custom 'visibility' field is set to 'public'
allow read: if resource.metadata.visibility == 'public';
}
}
}
}
Puoi anche utilizzare l'oggetto request.resource
nelle richieste write
(ad esempio
caricamenti, aggiornamenti dei metadati ed eliminazioni). L'oggetto request.resource
riceve
i metadati dal file che verrà scritto se write
è consentito.
Puoi utilizzare questi due valori per impedire aggiornamenti indesiderati o incoerenti o per applicare vincoli alle applicazioni, ad esempio tipo o dimensione del file.
service firebase.storage {
match /b/{bucket}/o {
match /images {
// 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) Filename (stored in imageId wildcard variable) is less than 32 characters
match /{imageId} {
allow read;
allow write: if request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*')
&& request.resource.contentType == resource.contentType
&& imageId.size() < 32
}
}
}
}
Un elenco completo delle proprietà nell'oggetto resource
è disponibile nella
documentazione di riferimento.