Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

Scrittura delle condizioni per le regole di sicurezza

Questa guida si basa sulla guida Struttura delle regole di sicurezza per mostrare come aggiungere condizioni alle regole di sicurezza di Firestore. Se non conosci le nozioni di base delle regole di sicurezza di Firestore, consulta la guida introduttiva.

La base è il componente di base delle regole di sicurezza di Firestore. Una condizione è un'espressione booleana che determina se una determinata operazione deve essere consentita o negata. Utilizza le regole di sicurezza per scrivere condizioni che controllino l'autenticazione utente, convalidino i dati in entrata o perfino ad accedere ad altre parti del tuo database.

Autenticazione

Uno dei pattern più comuni delle regole di sicurezza è il controllo degli accessi in base allo stato di autenticazione degli utenti. Ad esempio, la tua app potrebbe voler consentire solo agli utenti che hanno eseguito l'accesso di scrivere dati:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth != null;
    }
  }
}

Un altro schema comune è assicurarsi che gli utenti possano leggere e scrivere solo i propri dati:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null;
    }
  }
}

Se la tua app utilizza Firebase Authentication o Google Cloud Identity Platform, la variabile request.auth contiene le informazioni di autenticazione relative al client che richiede i dati. Per scoprire di più su request.auth, consulta la documentazione di riferimento.

Convalida dei dati

Molte app memorizzano le informazioni di controllo dell'accesso come campi nei documenti del database. Le regole di sicurezza di Firestore possono consentire o negare in modo dinamico un accesso in base ai dati di un 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 dei valori archiviati nel documento. Per saperne di più sulla variabile resource, consulta la documentazione di riferimento.

Quando scrivi i dati, potresti voler confrontare i dati in entrata con quelli esistenti. In questo caso, se il set di regole 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 indesiderati o incoerenti dei dati:

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

Accedi ad altri documenti

Utilizzando le funzioni get() e exists(), le regole di sicurezza possono valutare le richieste in entrata rispetto ad altri documenti nel database. Le funzioni get() e exists() prevedono entrambi percorsi di documenti completamente specificati. Quando utilizzi le variabili per creare percorsi per get() e exists(), devi eseguire esplicitamente l'escape delle variabili utilizzando la sintassi $(variable).

Nell'esempio riportato di seguito, la variabile database viene acquisita dall'istruzione di corrispondenza match /databases/{database}/documents e utilizzata per formare il percorso:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid))

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
    }
  }
}

Per le scritture, puoi utilizzare la funzione getAfter() per accedere allo stato di un documento dopo il completamento di una transazione o di un gruppo di operazioni di scrittura, ma prima che la transazione o il batch venga eseguito. Come get(), la funzione getAfter() richiede un percorso del documento completamente specificato. Puoi utilizzare getAfter() per definire insiemi di scritture che devono essere eseguiti insieme come transazione o batch.

Accedere ai limiti di chiamate

Esiste un limite per le chiamate di accesso ai documenti per la valutazione del set di regole:

  • 10 per richieste di documenti singoli e di query.
  • 20 per operazioni di lettura, transazione e scrittura in batch di più documenti. Il limite precedente di 10 si applica anche a ogni operazione.

    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 ogni scrittura. In questo caso, ogni scrittura utilizza 2 delle sue 10 chiamate di accesso e la richiesta di scrittura in batch utilizza 6 delle 20 chiamate di accesso.

Il superamento di uno dei limiti comporta un errore di autorizzazione negata. Alcune chiamate di accesso ai documenti possono essere memorizzate nella cache e le chiamate memorizzate nella cache non incidono sui limiti.

Per una spiegazione dettagliata di come questi limiti influiscono sulle transazioni e sulle scritture batch, consulta la guida alla sicurezza delle operazioni atomiche.

Accedi a chiamate e prezzi

Queste funzioni eseguono un'operazione di lettura nel database, il che significa che ti verrà addebitato il costo della lettura dei documenti anche se le regole rifiutano la richiesta. Consulta la pagina relativa ai prezzi diFirestore per informazioni di fatturazione più specifiche.

Funzioni personalizzate

Man mano che le regole di sicurezza diventano più complesse, puoi includere insiemi di condizioni in funzioni che puoi riutilizzare nel set di regole. Le regole di sicurezza supportano le funzioni personalizzate. La sintassi per le funzioni personalizzate è leggermente simile a JavaScript, ma le funzioni delle regole di sicurezza sono scritte in un linguaggio specifico del dominio con alcune limitazioni importanti.

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

Una funzione viene definita con la parola chiave function e non richiede alcun argomento. Ad esempio, potresti voler combinare i due tipi di condizioni utilizzati negli esempi in una singola 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();
    }
  }
}

L'uso delle funzioni nelle regole di sicurezza le rende più gestibili man mano che la complessità delle regole aumenta.

Le regole non sono filtri

Dopo aver protetto i dati e iniziato a scrivere query, tieni presente che le regole di sicurezza non sono filtri. Non puoi scrivere una query per tutti i documenti in una raccolta e aspettarti che Firestore restituisca solo i documenti a cui il client corrente è autorizzato ad accedere.

Ad esempio, adotta la seguente regola di sicurezza:

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

Negata: questa regola rifiuta la seguente query perché il set di risultati può includere documenti con valore visibility non pari a public:

Web
db.collection("cities").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
    });
});

Consentito: questa regola consente la seguente query perché la clausola where("visibility", "==", "public") garantisce che il set di risultati soddisfi la condizione della regola:

Web
db.collection("cities").where("visibility", "==", "public").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
        });
    });

Le regole di sicurezza di Firestore valutano ogni query in base al suo potenziale risultato e non superano la richiesta se potrebbero restituire un documento che il client non dispone dell'autorizzazione per leggere. Le query devono rispettare i vincoli impostati dalle regole di sicurezza. Per ulteriori informazioni sulle regole di sicurezza e sulle query, vedi Eseguire query sicure sui dati.

Passaggi successivi