Linguaggio delle regole di sicurezza

Le regole di sicurezza Firebase sfruttano linguaggi flessibili, potenti e personalizzati che supportano un'ampia gamma di complessità e granularità. Puoi rendere le tue regole tanto specifiche o generali quanto ha senso per la tua app. Le regole del Realtime Database utilizzano una sintassi simile a JavaScript in una struttura JSON. Le regole di Cloud Firestore e Cloud Storage utilizzano un linguaggio basato su Common Expression Language (CEL) , che si basa su CEL con istruzioni match e allow che supportano l'accesso concesso in modo condizionale.

Poiché si tratta di linguaggi personalizzati, tuttavia, esiste una curva di apprendimento. Utilizza questa guida per comprendere meglio il linguaggio delle regole mentre approfondisci regole più complesse.

Seleziona un prodotto per saperne di più sulle sue regole.

Struttura basilare

Cloud Fire Store

Le regole di sicurezza Firebase in Cloud Firestore e Cloud Storage utilizzano la struttura e la sintassi seguenti:

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

È importante comprendere i seguenti concetti chiave durante la creazione delle regole:

  • Richiesta: il metodo o i metodi richiamati nell'istruzione allow . Questi sono i metodi che stai consentendo di eseguire. I metodi standard sono: get , list , create , update e delete . I metodi pratici read e write consentono un ampio accesso in lettura e scrittura sul database o sul percorso di archiviazione specificato.
  • Percorso: il database o il percorso di archiviazione, rappresentato come percorso URI.
  • Regola: l'istruzione allow , che include una condizione che consente una richiesta se risulta vera.

Ciascuno di questi concetti è descritto più dettagliatamente di seguito.

Archiviazione nel cloud

Le regole di sicurezza Firebase in Cloud Firestore e Cloud Storage utilizzano la struttura e la sintassi seguenti:

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

È importante comprendere i seguenti concetti chiave durante la creazione delle regole:

  • Richiesta: il metodo o i metodi richiamati nell'istruzione allow . Questi sono i metodi che stai consentendo di eseguire. I metodi standard sono: get , list , create , update e delete . I metodi pratici read e write consentono un ampio accesso in lettura e scrittura sul database o sul percorso di archiviazione specificato.
  • Percorso: il database o il percorso di archiviazione, rappresentato come percorso URI.
  • Regola: l'istruzione allow , che include una condizione che consente una richiesta se risulta vera.

Ciascuno di questi concetti è descritto più dettagliatamente di seguito.

Banca dati in tempo reale

In Realtime Database, le regole di sicurezza Firebase sono costituite da espressioni simili a JavaScript contenute in un documento JSON.

Usano la seguente sintassi:

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

Ci sono tre elementi fondamentali nella regola:

  • Percorso: il percorso del database. Questo rispecchia la struttura JSON del tuo database.
  • Richiesta: questi sono i metodi utilizzati dalla regola per concedere l'accesso. Le regole read e write garantiscono un ampio accesso in lettura e scrittura, mentre le regole validate fungono da verifica secondaria per garantire l'accesso in base ai dati in entrata o esistenti.
  • Condizione: la condizione che consente una richiesta se risulta vera.

Costrutti di regole

Cloud Fire Store

Gli elementi di base di una regola in Cloud Firestore e Cloud Storage sono i seguenti:

  • La dichiarazione service : dichiara il prodotto Firebase a cui si applicano le regole.
  • Il blocco match : definisce un percorso nel database o nel bucket di archiviazione a cui si applicano le regole.
  • L' allow : fornisce le condizioni per concedere l'accesso, differenziate in base ai metodi. I metodi supportati includono: get , list , create , update , delete e i metodi pratici read e write .
  • Dichiarazioni function facoltative: offrono la possibilità di combinare e racchiudere condizioni da utilizzare su più regole.

Il service contiene uno o più blocchi match con istruzioni di allow che forniscono condizioni che garantiscono l'accesso alle richieste. Le variabili request e resource sono disponibili per l'uso nelle condizioni della regola. Il linguaggio Firebase Security Rules supporta anche le dichiarazioni function .

Versione della sintassi

L'istruzione di syntax indica la versione del linguaggio Firebase Rules utilizzato per scrivere l'origine. L'ultima versione del linguaggio è v2 .

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

Se non viene fornita alcuna istruzione rules_version , le regole verranno valutate utilizzando il motore v1 .

Servizio

La dichiarazione service definisce a quale prodotto o servizio Firebase si applicano le tue regole. Puoi includere solo una dichiarazione service per file di origine.

Cloud Fire Store

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

Archiviazione nel cloud

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

Se definisci regole sia per Cloud Firestore che per Cloud Storage utilizzando la CLI Firebase, dovrai mantenerle in file separati.

Incontro

Un blocco match dichiara un modello path che corrisponde al percorso per l'operazione richiesta (il request.path in entrata). Il corpo della match deve contenere uno o più blocchi match nidificati, istruzioni allow o dichiarazioni function . Il percorso nei blocchi match nidificati è relativo al percorso nel blocco match padre.

Il modello path è un nome simile a una directory che può includere variabili o caratteri jolly. Il modello path consente corrispondenze di segmenti a percorso singolo e di segmenti a percorso multiplo. Tutte le variabili legate a un path sono visibili nell'ambito della match o in qualsiasi ambito nidificato in cui è dichiarato il path .

Le corrispondenze con un modello path possono essere parziali o complete:

  • Corrispondenze parziali: il modello path è una corrispondenza del prefisso di request.path .
  • Corrispondenze complete: il modello path corrisponde all'intero request.path .

Quando viene effettuata una corrispondenza completa , vengono valutate le regole all'interno del blocco. Quando viene effettuata una corrispondenza parziale , le regole match nidificate vengono testate per verificare se un path nidificato completerà la corrispondenza.

Le regole di ogni match completa vengono valutate per determinare se consentire la richiesta. Se una qualsiasi regola corrispondente concede l'accesso, la richiesta è consentita. Se nessuna regola corrispondente concede l'accesso, la richiesta viene negata.

// 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.
  }
}

Come mostra l'esempio sopra, le dichiarazioni path supportano le seguenti variabili:

  • Carattere jolly a segmento singolo: una variabile jolly viene dichiarata in un percorso racchiudendo una variabile tra parentesi graffe: {variable} . Questa variabile è accessibile all'interno dell'istruzione match come una string .
  • Carattere jolly ricorsivo: il carattere jolly ricorsivo o multisegmento corrisponde a più segmenti di percorso in corrispondenza o al di sotto di un percorso. Questo carattere jolly corrisponde a tutti i percorsi sotto la posizione in cui lo hai impostato. Puoi dichiararlo aggiungendo la stringa =** alla fine della variabile del segmento: {variable=**} . Questa variabile è accessibile all'interno dell'istruzione match come oggetto path .

Permettere

Il blocco match contiene una o più istruzioni allow . Queste sono le tue vere regole. È possibile applicare le regole allow a uno o più metodi. Le condizioni su un'istruzione di allow devono essere valutate come true affinché Cloud Firestore o Cloud Storage possano concedere qualsiasi richiesta in arrivo. Puoi anche scrivere istruzioni allow senza condizioni, ad esempio allow read . Se l' allow non include una condizione, tuttavia, consente sempre la richiesta per quel metodo.

Se una qualsiasi delle regole allow per il metodo viene soddisfatta, la richiesta viene consentita. Inoltre, se una regola più ampia concede l'accesso, le Regole concedono l'accesso e ignorano eventuali regole più granulari che potrebbero limitare l'accesso.

Considera l'esempio seguente, in cui qualsiasi utente può leggere o eliminare i propri file. Una regola più granulare consente le scritture solo se l'utente che richiede la scrittura possiede il file e il file è un PNG. Un utente può eliminare qualsiasi file nel sottopercorso, anche se non sono PNG, perché la regola precedente lo consente.

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');
  }
}

Metodo

Ciascuna istruzione allow include un metodo che concede l'accesso per le richieste in entrata dello stesso metodo.

Metodo Tipo di richiesta
Metodi di convenienza
read Qualsiasi tipo di richiesta di lettura
write Qualsiasi tipo di richiesta di scrittura
Metodi standard
get Leggere richieste di singoli documenti o file
list Leggere le richieste di interrogazioni e raccolte
create Scrivere nuovi documenti o file
update Scrivi su documenti di database esistenti o aggiorna i metadati dei file
delete Elimina dati

Non è possibile sovrapporre metodi di lettura nello stesso blocco match o metodi di scrittura in conflitto nella stessa dichiarazione path .

Ad esempio, le seguenti regole fallirebbero:

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";
    }
  }
}

Funzione

Man mano che le regole di sicurezza diventano più complesse, potresti voler racchiudere serie di condizioni in funzioni che puoi riutilizzare nel tuo set di regole. Le regole di sicurezza supportano funzioni personalizzate. La sintassi per le funzioni personalizzate è un po' come JavaScript, ma le funzioni delle regole di sicurezza sono scritte in un linguaggio specifico del dominio che presenta alcune importanti limitazioni:

  • Le funzioni possono contenere solo una singola istruzione return . Non possono contenere alcuna logica aggiuntiva. Ad esempio, non possono eseguire cicli o chiamare servizi esterni.
  • Le funzioni possono accedere automaticamente a funzioni e variabili dall'ambito in cui sono definite. Ad esempio, una funzione definita nell'ambito del service cloud.firestore ha accesso alla variabile resource e alle funzioni integrate come get() ed exists() .
  • Le funzioni possono chiamare altre funzioni ma non possono ricorrere. La profondità totale dello stack di chiamate è limitata a 20.
  • Nella versione v2 delle regole, le funzioni possono definire variabili utilizzando la parola chiave let . Le funzioni possono avere fino a 10 associazioni let, ma devono terminare con un'istruzione return.

Una funzione è definita con la parola chiave function e accetta zero o più argomenti. Ad esempio, potresti voler combinare i due tipi di condizioni utilizzati negli esempi precedenti in un'unica funzione:

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();
    }
  }
}

Ecco un esempio che mostra gli argomenti della funzione e le assegnazioni let. Le istruzioni di assegnazione Let devono essere separate da punto e virgola.

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

Nota come l'assegnazione isAdmin impone una ricerca della raccolta admins. Per una valutazione pigra senza richiedere ricerche non necessarie, sfruttare la natura di cortocircuito di && (AND) e || (OR) confronti per chiamare una seconda funzione solo se isAuthor risulta essere vero (per i confronti && ) o falso (per i confronti || ).

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'utilizzo delle funzioni nelle regole di sicurezza le rende più gestibili man mano che la complessità delle regole aumenta.

Archiviazione nel cloud

Gli elementi di base di una regola in Cloud Firestore e Cloud Storage sono i seguenti:

  • La dichiarazione service : dichiara il prodotto Firebase a cui si applicano le regole.
  • Il blocco match : definisce un percorso nel database o nel bucket di archiviazione a cui si applicano le regole.
  • L' allow : fornisce le condizioni per concedere l'accesso, differenziate in base ai metodi. I metodi supportati includono: get , list , create , update , delete e i metodi pratici read e write .
  • Dichiarazioni function facoltative: offrono la possibilità di combinare e racchiudere condizioni da utilizzare su più regole.

Il service contiene uno o più blocchi match con istruzioni di allow che forniscono condizioni che garantiscono l'accesso alle richieste. Le variabili request e resource sono disponibili per l'uso nelle condizioni della regola. Il linguaggio Firebase Security Rules supporta anche le dichiarazioni function .

Versione della sintassi

L'istruzione di syntax indica la versione del linguaggio Firebase Rules utilizzato per scrivere l'origine. L'ultima versione del linguaggio è v2 .

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

Se non viene fornita alcuna istruzione rules_version , le regole verranno valutate utilizzando il motore v1 .

Servizio

La dichiarazione service definisce a quale prodotto o servizio Firebase si applicano le tue regole. Puoi includere solo una dichiarazione service per file di origine.

Cloud Fire Store

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

Archiviazione nel cloud

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

Se definisci regole sia per Cloud Firestore che per Cloud Storage utilizzando la CLI Firebase, dovrai mantenerle in file separati.

Incontro

Un blocco match dichiara un modello path che corrisponde al percorso per l'operazione richiesta (il request.path in entrata). Il corpo della match deve contenere uno o più blocchi match nidificati, istruzioni allow o dichiarazioni function . Il percorso nei blocchi match nidificati è relativo al percorso nel blocco match padre.

Il modello path è un nome simile a una directory che può includere variabili o caratteri jolly. Il modello path consente corrispondenze di segmenti a percorso singolo e di segmenti a percorso multiplo. Tutte le variabili legate a un path sono visibili nell'ambito della match o in qualsiasi ambito nidificato in cui è dichiarato il path .

Le corrispondenze con un modello path possono essere parziali o complete:

  • Corrispondenze parziali: il modello path è una corrispondenza del prefisso di request.path .
  • Corrispondenze complete: il modello path corrisponde all'intero request.path .

Quando viene effettuata una corrispondenza completa , vengono valutate le regole all'interno del blocco. Quando viene effettuata una corrispondenza parziale , le regole match nidificate vengono testate per verificare se un path nidificato completerà la corrispondenza.

Le regole di ogni match completa vengono valutate per determinare se consentire la richiesta. Se una qualsiasi regola corrispondente concede l'accesso, la richiesta è consentita. Se nessuna regola corrispondente concede l'accesso, la richiesta viene negata.

// 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.
  }
}

Come mostra l'esempio sopra, le dichiarazioni path supportano le seguenti variabili:

  • Carattere jolly a segmento singolo: una variabile jolly viene dichiarata in un percorso racchiudendo una variabile tra parentesi graffe: {variable} . Questa variabile è accessibile all'interno dell'istruzione match come una string .
  • Carattere jolly ricorsivo: il carattere jolly ricorsivo o multisegmento corrisponde a più segmenti di percorso in corrispondenza o al di sotto di un percorso. Questo carattere jolly corrisponde a tutti i percorsi sotto la posizione in cui lo hai impostato. Puoi dichiararlo aggiungendo la stringa =** alla fine della variabile del segmento: {variable=**} . Questa variabile è accessibile all'interno dell'istruzione match come oggetto path .

Permettere

Il blocco match contiene una o più istruzioni allow . Queste sono le tue vere regole. È possibile applicare le regole allow a uno o più metodi. Le condizioni su un'istruzione di allow devono essere valutate come true affinché Cloud Firestore o Cloud Storage possano concedere qualsiasi richiesta in arrivo. Puoi anche scrivere istruzioni allow senza condizioni, ad esempio allow read . Se l' allow non include una condizione, tuttavia, consente sempre la richiesta per quel metodo.

Se una qualsiasi delle regole allow per il metodo viene soddisfatta, la richiesta viene consentita. Inoltre, se una regola più ampia concede l'accesso, le Regole concedono l'accesso e ignorano eventuali regole più granulari che potrebbero limitare l'accesso.

Considera l'esempio seguente, in cui qualsiasi utente può leggere o eliminare i propri file. Una regola più granulare consente le scritture solo se l'utente che richiede la scrittura possiede il file e il file è un PNG. Un utente può eliminare qualsiasi file nel sottopercorso, anche se non sono PNG, perché la regola precedente lo consente.

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');
  }
}

Metodo

Ciascuna istruzione allow include un metodo che concede l'accesso per le richieste in entrata dello stesso metodo.

Metodo Tipo di richiesta
Metodi di convenienza
read Qualsiasi tipo di richiesta di lettura
write Qualsiasi tipo di richiesta di scrittura
Metodi standard
get Leggere richieste di singoli documenti o file
list Leggere le richieste di interrogazioni e raccolte
create Scrivere nuovi documenti o file
update Scrivi su documenti di database esistenti o aggiorna i metadati dei file
delete Elimina dati

Non è possibile sovrapporre metodi di lettura nello stesso blocco match o metodi di scrittura in conflitto nella stessa dichiarazione path .

Ad esempio, le seguenti regole fallirebbero:

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";
    }
  }
}

Funzione

Man mano che le regole di sicurezza diventano più complesse, potresti voler racchiudere serie di condizioni in funzioni che puoi riutilizzare nel tuo set di regole. Le regole di sicurezza supportano funzioni personalizzate. La sintassi per le funzioni personalizzate è un po' come JavaScript, ma le funzioni delle regole di sicurezza sono scritte in un linguaggio specifico del dominio che presenta alcune importanti limitazioni:

  • Le funzioni possono contenere solo una singola istruzione return . Non possono contenere alcuna logica aggiuntiva. Ad esempio, non possono eseguire cicli o chiamare servizi esterni.
  • Le funzioni possono accedere automaticamente a funzioni e variabili dall'ambito in cui sono definite. Ad esempio, una funzione definita nell'ambito del service cloud.firestore ha accesso alla variabile resource e alle funzioni integrate come get() ed exists() .
  • Le funzioni possono chiamare altre funzioni ma non possono ricorrere. La profondità totale dello stack di chiamate è limitata a 20.
  • Nella versione v2 delle regole, le funzioni possono definire variabili utilizzando la parola chiave let . Le funzioni possono avere fino a 10 associazioni let, ma devono terminare con un'istruzione return.

Una funzione è definita con la parola chiave function e accetta zero o più argomenti. Ad esempio, potresti voler combinare i due tipi di condizioni utilizzati negli esempi precedenti in un'unica funzione:

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();
    }
  }
}

Ecco un esempio che mostra gli argomenti della funzione e le assegnazioni let. Le istruzioni di assegnazione Let devono essere separate da punto e virgola.

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

Nota come l'assegnazione isAdmin impone una ricerca della raccolta admins. Per una valutazione pigra senza richiedere ricerche non necessarie, sfruttare la natura di cortocircuito di && (AND) e || (OR) confronti per chiamare una seconda funzione solo se isAuthor risulta essere vero (per i confronti && ) o falso (per i confronti || ).

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'utilizzo delle funzioni nelle regole di sicurezza le rende più gestibili man mano che la complessità delle regole aumenta.

Banca dati in tempo reale

Come sottolineato in precedenza, le regole del database in tempo reale includono tre elementi di base: la posizione del database come specchio della struttura JSON del database, il tipo di richiesta e la condizione che garantisce l'accesso.

Posizione della banca dati

La struttura delle tue regole dovrebbe seguire la struttura dei dati che hai archiviato nel tuo database. Ad esempio, in un'app di chat con un elenco di messaggi, potresti avere dati simili a questi:

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

Le tue regole dovrebbero rispecchiare quella struttura. Per esempio:

  {
    "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()"
        }
      }
    }
  }

Come mostra l'esempio precedente, le regole del database in tempo reale supportano una variabile $location per far corrispondere i segmenti di percorso. Utilizza il prefisso $ davanti al segmento del percorso per abbinare la regola a qualsiasi nodo figlio lungo il percorso.

  {
    "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')"
          }
        }
      }
    }
  }

Puoi anche utilizzare la $variable in parallelo con nomi di percorso costanti.

  {
    "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 }
      }
    }
  }

Metodo

In Realtime Database esistono tre tipi di regole. Due di questi tipi di regole, read e write , si applicano al metodo di una richiesta in entrata. Il tipo di regola validate applica le strutture dei dati e convalida il formato e il contenuto dei dati. Le regole eseguono le regole .validate dopo aver verificato che una regola .write concede l'accesso.

Tipi di regole
.Leggere Descrive se e quando i dati possono essere letti dagli utenti.
.scrivere Descrive se e quando è consentita la scrittura dei dati.
.convalidare Definisce l'aspetto di un valore formattato correttamente, se ha attributi secondari e il tipo di dati.

Per impostazione predefinita, se non esiste una regola che lo consente, l'accesso a un percorso viene negato.

Condizioni edilizie

Cloud Fire Store

Una condizione è un'espressione booleana che determina se una particolare operazione deve essere consentita o negata. Le variabili request e resource forniscono il contesto per tali condizioni.

La variabile request

La variabile request include i seguenti campi e le informazioni corrispondenti:

request.auth

Un token Web JSON (JWT) che contiene le credenziali di autenticazione da Firebase Authentication. Il token auth contiene una serie di attestazioni standard ed eventuali attestazioni personalizzate create tramite l'autenticazione Firebase. Ulteriori informazioni sulle regole di sicurezza e sull'autenticazione di Firebase .

request.method

Il request.method può essere uno qualsiasi dei metodi standard o un metodo personalizzato. I metodi pratici read e write esistono anche per semplificare le regole di scrittura che si applicano rispettivamente a tutti i metodi standard di sola lettura o di sola scrittura.

request.params

request.params include tutti i dati non specificamente correlati a request.resource che potrebbero essere utili per la valutazione. In pratica, questa mappa dovrebbe essere vuota per tutti i metodi standard e dovrebbe contenere dati non di risorse per i metodi personalizzati. I servizi devono fare attenzione a non rinominare o modificare il tipo di chiavi e valori presentati come parametri.

request.path

request.path è il percorso della resource di destinazione. Il percorso è relativo al servizio. I segmenti di percorso contenenti caratteri non sicuri per l'URL come / sono codificati nell'URL.

La variabile della resource

La resource è il valore corrente all'interno del servizio rappresentato come una mappa di coppie chiave-valore. Fare riferimento a resource all'interno di una condizione comporterà al massimo una lettura del valore dal servizio. Questa ricerca verrà conteggiata rispetto a qualsiasi quota relativa al servizio per la risorsa. Per le richieste get , la resource verrà conteggiata solo ai fini della quota in caso di rifiuto.

Operatori e precedenza degli operatori

Utilizza la tabella seguente come riferimento per gli operatori e la loro precedenza corrispondente nelle Regole per Cloud Firestore e Cloud Storage.

Date le espressioni arbitrarie a e b , un campo f e un indice i .

Operatore Descrizione Associatività
a[i] a() af Indice, chiamata, accesso al campo da sinistra a destra
!a -a Negazione unaria da destra a sinistra
a/ba%ba*b Operatori moltiplicativi da sinistra a destra
a+b ab Operatori additivi da sinistra a destra
a>ba>=ba Operatori relazionali da sinistra a destra
a in b Esistenza in elenco o mappa da sinistra a destra
a is type Confronto di tipi, dove type può essere bool, int, float, numero, stringa, elenco, mappa, timestamp, durata, percorso o latlng da sinistra a destra
a==ba!=b Operatori di confronto da sinistra a destra
a && b Condizionale AND da sinistra a destra
a || b OR condizionale da sinistra a destra
a ? true_value : false_value Espressione ternaria da sinistra a destra

Archiviazione nel cloud

Una condizione è un'espressione booleana che determina se una particolare operazione deve essere consentita o negata. Le variabili request e resource forniscono il contesto per tali condizioni.

La variabile request

La variabile request include i seguenti campi e le informazioni corrispondenti:

request.auth

Un token Web JSON (JWT) che contiene le credenziali di autenticazione da Firebase Authentication. Il token auth contiene una serie di attestazioni standard ed eventuali attestazioni personalizzate create tramite l'autenticazione Firebase. Ulteriori informazioni sulle regole di sicurezza e sull'autenticazione di Firebase .

request.method

Il request.method può essere uno qualsiasi dei metodi standard o un metodo personalizzato. I metodi pratici read e write esistono anche per semplificare le regole di scrittura che si applicano rispettivamente a tutti i metodi standard di sola lettura o di sola scrittura.

request.params

request.params include tutti i dati non specificamente correlati a request.resource che potrebbero essere utili per la valutazione. In pratica, questa mappa dovrebbe essere vuota per tutti i metodi standard e dovrebbe contenere dati non di risorse per i metodi personalizzati. I servizi devono fare attenzione a non rinominare o modificare il tipo di chiavi e valori presentati come parametri.

request.path

request.path è il percorso della resource di destinazione. Il percorso è relativo al servizio. I segmenti di percorso contenenti caratteri non sicuri per l'URL come / sono codificati nell'URL.

La variabile della resource

La resource è il valore corrente all'interno del servizio rappresentato come una mappa di coppie chiave-valore. Fare riferimento a resource all'interno di una condizione comporterà al massimo una lettura del valore dal servizio. Questa ricerca verrà conteggiata rispetto a qualsiasi quota relativa al servizio per la risorsa. Per le richieste get , la resource verrà conteggiata solo ai fini della quota in caso di rifiuto.

Operatori e precedenza degli operatori

Utilizza la tabella seguente come riferimento per gli operatori e la loro precedenza corrispondente nelle Regole per Cloud Firestore e Cloud Storage.

Date le espressioni arbitrarie a e b , un campo f e un indice i .

Operatore Descrizione Associatività
a[i] a() af Indice, chiamata, accesso al campo da sinistra a destra
!a -a Negazione unaria da destra a sinistra
a/ba%ba*b Operatori moltiplicativi da sinistra a destra
a+b ab Operatori additivi da sinistra a destra
a>ba>=ba Operatori relazionali da sinistra a destra
a in b Esistenza in elenco o mappa da sinistra a destra
a is type Confronto di tipi, dove type può essere bool, int, float, numero, stringa, elenco, mappa, timestamp, durata, percorso o latlng da sinistra a destra
a==ba!=b Operatori di confronto da sinistra a destra
a && b Condizionale AND da sinistra a destra
a || b OR condizionale da sinistra a destra
a ? true_value : false_value Espressione ternaria da sinistra a destra

Banca dati in tempo reale

Una condizione è un'espressione booleana che determina se una particolare operazione deve essere consentita o negata. È possibile definire tali condizioni nelle Regole del database in tempo reale nei seguenti modi.

Variabili predefinite

Esistono numerose variabili utili e predefinite a cui è possibile accedere all'interno della definizione di una regola. Ecco un breve riepilogo di ciascuno:

Variabili predefinite
Ora L'ora corrente in millisecondi dall'epoca di Linux. Funziona particolarmente bene per convalidare i timestamp creati con firebase.database.ServerValue.TIMESTAMP dell'SDK.
radice Un RuleDataSnapshot che rappresenta il percorso root nel database Firebase così come esisteva prima dell'operazione tentata.
newData Un RuleDataSnapshot che rappresenta i dati come esisterebbero dopo il tentativo di operazione. Include i nuovi dati in fase di scrittura e i dati esistenti.
dati Un RuleDataSnapshot che rappresenta i dati così come esistevano prima dell'operazione tentata.
variabili $ Un percorso con caratteri jolly utilizzato per rappresentare ID e chiavi figlio dinamiche.
aut Rappresenta il payload del token di un utente autenticato.

Queste variabili possono essere utilizzate ovunque nelle regole. Ad esempio, le regole di sicurezza seguenti garantiscono che i dati scritti sul nodo /foo/ debbano essere una stringa inferiore a 100 caratteri:

{
  "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"
    }
  }
}

Regole basate sui dati

Tutti i dati presenti nel database possono essere utilizzati nelle regole. Utilizzando le variabili predefinite root , data e newData , è possibile accedere a qualsiasi percorso così come esisterebbe prima o dopo un evento di scrittura.

Considera questo esempio, che consente operazioni di scrittura fintanto che il valore del nodo /allow_writes/ è true , il nodo genitore non ha un flag readOnly impostato e c'è un figlio chiamato foo nei dati appena scritti:

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

Regole basate su query

Sebbene non sia possibile utilizzare le regole come filtri, puoi limitare l'accesso a sottoinsiemi di dati utilizzando i parametri di query nelle regole. Usa query. espressioni nelle regole per concedere l'accesso in lettura o scrittura in base ai parametri di query.

Ad esempio, la seguente regola basata su query utilizza regole di sicurezza basate sull'utente e regole basate su query per limitare l'accesso ai dati nella raccolta baskets solo ai carrelli degli acquisti di proprietà dell'utente attivo:

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

La seguente query, che include i parametri di query nella regola, avrebbe esito positivo:

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

Tuttavia, le query che non includono i parametri nella regola fallirebbero con un errore PermissionDenied :

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

È inoltre possibile utilizzare regole basate su query per limitare la quantità di dati scaricati da un client tramite operazioni di lettura.

Ad esempio, la regola seguente limita l'accesso in lettura solo ai primi 1000 risultati di una query, ordinati per 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 seguente query. le espressioni sono disponibili nelle regole di sicurezza del database in tempo reale.

Espressioni di regole basate su query
Espressione Tipo Descrizione
query.orderByKey
query.orderByPriority
query.orderByValue
booleano Vero per le query ordinate per chiave, priorità o valore. Falso altrimenti.
query.orderByChild corda
nullo
Utilizzare una stringa per rappresentare il percorso relativo a un nodo figlio. Ad esempio, query.orderByChild === "address/zip" . Se la query non è ordinata da un nodo figlio, questo valore è null.
query.startAt
query.endAt
query.equalTo
corda
numero
booleano
nullo
Recupera i limiti della query in esecuzione o restituisce null se non è impostato alcun limite.
query.limitToFirst
query.limitToLast
numero
nullo
Recupera il limite sulla query in esecuzione o restituisce null se non è impostato alcun limite.

Operatori

Le regole del database in tempo reale supportano una serie di operatori che è possibile utilizzare per combinare le variabili nell'istruzione condizionale. Consulta l'elenco completo degli operatori nella documentazione di riferimento .

Creare condizioni

Le tue condizioni effettive varieranno in base all'accesso che desideri concedere. Le regole offrono intenzionalmente un enorme grado di flessibilità, quindi le regole della tua app possono essere semplici o complesse a seconda delle tue esigenze.

Per alcune indicazioni sulla creazione di regole semplici e pronte per la produzione, consulta Regole di sicurezza di base .