Strutturazione delle regole di sicurezza di Cloud Firestore

Le regole di sicurezza di Cloud Firestore ti consentono di controllare l'accesso ai documenti e alle raccolte nel tuo database. La sintassi flessibile delle regole ti consente di creare regole che corrispondono a qualsiasi cosa, da tutte le scritture sull'intero database alle operazioni su un documento specifico.

Questa guida descrive la sintassi di base e la struttura delle regole di sicurezza. Combina questa sintassi con le condizioni delle regole di sicurezza per creare set di regole completi.

Dichiarazione di servizi e database

Le regole di sicurezza di Cloud Firestore iniziano sempre con la seguente dichiarazione:

service cloud.firestore {
  match /databases/{database}/documents {
    // ...
  }
}

La dichiarazione del service cloud.firestore estende le regole a Cloud Firestore, prevenendo conflitti tra le regole di sicurezza di Cloud Firestore e le regole per altri prodotti come Cloud Storage.

La dichiarazione match /databases/{database}/documents specifica che le regole devono corrispondere a qualsiasi database Cloud Firestore nel progetto. Attualmente ogni progetto ha un solo database denominato (default) .

Regole di lettura/scrittura di base

Le regole di base consistono in un'istruzione match che specifica un percorso del documento e un'espressione allow che descrive in dettaglio quando è consentita la lettura dei dati specificati:

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

Tutte le dichiarazioni di corrispondenza dovrebbero puntare a documenti, non a raccolte. Un'istruzione match può puntare a un documento specifico, come in match /cities/SF o utilizzare caratteri jolly per puntare a qualsiasi documento nel percorso specificato, come in match /cities/{city} .

Nell'esempio precedente, l'istruzione match utilizza la sintassi del carattere jolly {city} . Ciò significa che la regola si applica a qualsiasi documento nella raccolta cities , come /cities/SF o /cities/NYC . Quando vengono valutate le espressioni allow nell'istruzione match, la variabile city verrà risolta nel nome del documento della città, come SF o NYC .

Operazioni granulari

In alcune situazioni è utile suddividere read e write in operazioni più granulari. Ad esempio, la tua app potrebbe voler applicare condizioni diverse alla creazione dei documenti rispetto all'eliminazione dei documenti. Oppure potresti voler consentire la lettura di singoli documenti ma negare query di grandi dimensioni.

Una regola read può essere suddivisa in get e list , mentre una regola write può essere suddivisa in create , update e delete :

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
}

Dati gerarchici

I dati in Cloud Firestore sono organizzati in raccolte di documenti e ogni documento può estendere la gerarchia tramite sottoraccolte. È importante comprendere come le regole di sicurezza interagiscono con i dati gerarchici.

Considera la situazione in cui ogni documento nella raccolta delle cities contiene una sottoraccolta landmarks . Le regole di sicurezza si applicano solo al percorso corrispondente, quindi i controlli di accesso definiti nella raccolta cities non si applicano alla sottoraccolta landmarks . Scrivi invece regole esplicite per controllare l'accesso alle sottoraccolte:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

Quando si annidano le istruzioni match , il percorso dell'istruzione match interna è sempre relativo al percorso dell'istruzione match esterna. Le seguenti regole sono quindi equivalenti:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

Caratteri jolly ricorsivi

Se desideri che le regole si applichino a una gerarchia arbitrariamente profonda, utilizza la sintassi ricorsiva dei caratteri jolly, {name=**} . Per esempio:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

Quando si utilizza la sintassi ricorsiva dei caratteri jolly, la variabile dei caratteri jolly conterrà l'intero segmento del percorso corrispondente, anche se il documento si trova in una sottoraccolta profondamente nidificata. Ad esempio, le regole elencate sopra corrisponderebbero a un documento situato in /cities/SF/landmarks/coit_tower e il valore della variabile document sarebbe SF/landmarks/coit_tower .

Si noti, tuttavia, che il comportamento dei caratteri jolly ricorsivi dipende dalla versione delle regole.

Versione 1

Le regole di sicurezza utilizzano la versione 1 per impostazione predefinita. Nella versione 1, i caratteri jolly ricorsivi corrispondono a uno o più elementi del percorso. Non corrispondono a un percorso vuoto, quindi match /cities/{city}/{document=**} corrisponde ai documenti nelle sottoraccolte ma non nella raccolta cities , mentre match /cities/{document=**} corrisponde ad entrambi i documenti nella collezione e sottocollezioni cities .

I caratteri jolly ricorsivi devono trovarsi alla fine di un'istruzione di corrispondenza.

Versione 2

Nella versione 2 delle regole di sicurezza, i caratteri jolly ricorsivi corrispondono a zero o più elementi del percorso. match/cities/{city}/{document=**} abbina i documenti in qualsiasi sottoraccolta così come i documenti nella raccolta cities .

Devi aderire alla versione 2 aggiungendo rules_version = '2'; in cima alle tue regole di sicurezza:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

Puoi avere al massimo un carattere jolly ricorsivo per ogni istruzione di corrispondenza, ma nella versione 2 puoi inserire questo carattere jolly ovunque nell'istruzione di corrispondenza. Per esempio:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

Se utilizzi le query sui gruppi di raccolta , devi utilizzare la versione 2, consulta Protezione delle query sui gruppi di raccolta .

Dichiarazioni di corrispondenza sovrapposte

È possibile che un documento corrisponda a più di un'istruzione match . Nel caso in cui più espressioni allow corrispondano a una richiesta, l'accesso è consentito se una delle condizioni è true :

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

Nell'esempio precedente, tutte le operazioni di lettura e scrittura nella raccolta cities saranno consentite perché la seconda regola è sempre true , anche se la prima regola è sempre false .

Limiti delle regole di sicurezza

Mentre lavori con le regole di sicurezza, tieni presente i seguenti limiti:

Limite Dettagli
Numero massimo di chiamate exists() , get() e getAfter() per richiesta
  • 10 per richieste di documento singolo e richieste di interrogazione.
  • 20 per letture di più documenti, transazioni e scritture in batch. Per ogni operazione vale anche il precedente limite di 10.

    Ad esempio, immagina di creare una richiesta di scrittura in batch con 3 operazioni di scrittura e che le regole di sicurezza utilizzino 2 chiamate di accesso ai documenti per convalidare ciascuna scrittura. In questo caso, ciascuna scrittura utilizza 2 delle sue 10 chiamate di accesso e la richiesta di scrittura in batch utilizza 6 delle sue 20 chiamate di accesso.

Il superamento di uno dei limiti genera un errore di autorizzazione negata.

Alcune chiamate di accesso ai documenti potrebbero essere memorizzate nella cache e le chiamate memorizzate nella cache non vengono conteggiate ai fini dei limiti.

Profondità massima delle istruzioni match nidificate 10
Lunghezza massima del percorso, in segmenti di percorso, consentita all'interno di una serie di istruzioni match nidificate 100
Numero massimo di variabili di acquisizione del percorso consentite all'interno di una serie di istruzioni match nidificate 20
Profondità massima delle chiamate di funzione 20
Numero massimo di argomenti della funzione 7
Numero massimo di associazioni di variabili let per funzione 10
Numero massimo di chiamate di funzioni ricorsive o cicliche 0 (non consentito)
Numero massimo di espressioni valutate per richiesta 1.000
Dimensione massima di un set di regole I set di regole devono rispettare due limiti di dimensione:
  • un limite di 256 KB sulla dimensione dell'origine del testo del set di regole pubblicata dalla console Firebase o dalla CLI utilizzando firebase deploy .
  • un limite di 250 KB sulla dimensione del set di regole compilato che risulta quando Firebase elabora l'origine e la rende attiva sul back-end.

Prossimi passi