Scrivi le condizioni per le regole di sicurezza

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

Il componente di base principale delle regole di sicurezza di Firestore è la condizione. 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 addirittura accedano ad altre parti del tuo database.

Autenticazione

Uno dei pattern di regole di sicurezza più comuni è il controllo dell'accesso in base allo stato di autenticazione dell'utente. Ad esempio, l'app potrebbe voler consentire utenti che hanno eseguito l'accesso per 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 pattern 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 per il client che richiede i dati. Per ulteriori informazioni su request.auth, consulta la documentazione di riferimento documentazione.

Convalida dei dati

Molte app archiviano le informazioni sul controllo dell'accesso come campi nei documenti del database. Le regole di sicurezza di Firestore possono consentire o negare dinamicamente l'accesso in base al documento dati:

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 fa riferimento al documento richiesto, mentre resource.data è una mappa di tutti i campi e i valori archiviati nel documento. Per maggiori informazioni informazioni sulla variabile resource, consulta il riferimento documentazione.

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, request.resource contiene lo stato futuro del documento. Per le operazioni update che modificano solo un sottoinsieme di 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 di 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;
    }
  }
}

Accedere ad altri documenti

Utilizzando le funzioni get() e exists(), le regole di sicurezza possono valutare le richieste in arrivo in base ad altri documenti nel database. Le funzioni get() e exists() prevedono entrambe percorsi dei documenti completamente specificati. Quando utilizzi variabili per creare percorsi per get() e exists(), devi eseguire esplicitamente la codifica delle variabili utilizzando la sintassi $(variable).

Nell'esempio seguente, la variabile database viene acquisita dalla corrispondenza l'istruzione match /databases/{database}/documents e utilizzata per creare 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 una documento dopo il completamento di una transazione o di un gruppo di scritture, ma prima che di transazioni o batch. Come nel caso di get(), la funzione getAfter() utilizza una completamente specificato. Puoi utilizzare getAfter() per definire insiemi di scritture che devono essere eseguite insieme come transazione o batch.

Limiti di accesso alle chiamate

Esiste un limite alle chiamate di accesso ai documenti per valutazione di una serie di regole:

  • 10 per richieste di documenti singoli e di query.
  • 20 per letture di più documenti, transazioni e le scritture in batch. Il limite precedente di 10 si applica anche a operativa.

    Ad esempio, immagina di creare una richiesta di scrittura in batch con 3 operazioni di scrittura e che le tue regole di sicurezza utilizzino 2 chiamate di accesso ai documenti per convalidare ogni operazione di scrittura. In questo caso, ogni operazione di 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 comporta un errore di autorizzazione negata. Documento le chiamate di accesso possono essere memorizzate nella cache e le chiamate memorizzate nella cache non vengono conteggiate ai fini dei limiti.

Per una spiegazione dettagliata di come questi limiti influiscono sulle transazioni e sulle scritture collettive, consulta la guida per la protezione delle operazioni atomiche.

Accedi alle chiamate e ai prezzi

L'utilizzo di queste funzioni esegue un'operazione di lettura nel database, Ciò significa che ti verrà addebitato il costo della lettura dei documenti anche se le tue regole vengono rifiutate la richiesta. Per informazioni di fatturazione più specifiche, consulta Prezzi di Firestore.

Funzioni personalizzate

Man mano che le regole di sicurezza diventano più complesse, è consigliabile aggregare insiemi in funzioni riutilizzabili nel set di regole. Le regole di sicurezza supportano le 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 che presenta alcune importanti limitazioni:

  • Le funzioni possono contenere una sola istruzione return. Non possono contenere alcuna logica aggiuntiva. Ad esempio, non possono eseguire loop o chiamare servizi esterni.
  • Le funzioni possono accedere automaticamente alle funzioni e alle variabili dall'ambito in cui sono definite. Ad esempio, una funzione definita all'interno dell'ambito service cloud.firestore ha accesso alla variabile resource e alle funzioni incorporate come get() e exists().
  • Le funzioni possono chiamare altre funzioni ma non sono ricorrenti. La chiamata totale la profondità dello stack è limitata a 10.
  • Nella versione delle regole v2, le funzioni possono definire le variabili utilizzando la parola chiave let. Le funzioni possono avere fino a 10 associazioni Consenti, ma devono terminare con un ritorno l'Informativa.

Una funzione viene definita con la parola chiave function e prende zero o più argomenti. Ad esempio, potresti voler combinare i due tipi di condizioni utilizzati gli 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();
    }
  }
}

L'utilizzo di funzioni nelle regole di sicurezza ne rende più gestibili la complessità delle regole aumenta.

Le regole non sono filtri

Dopo aver protetto i dati e aver iniziato a scrivere query, tieni presente che le regole non sono filtri. Non puoi scrivere una query per tutti i documenti in un e si aspetta che Firestore restituisca solo i documenti che il client attuale dispone dell'autorizzazione ad accedere.

Ad esempio, prendi in considerazione 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';
    }
  }
}

Rifiutato: questa regola rifiuta la seguente query perché il set di risultati può includere documenti in cui visibility non è 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:

A rete
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 completano la richiesta se potrebbe restituire un documento per cui il client non ha l'autorizzazione di lettura. Le query devono seguire i vincoli impostati le regole di sicurezza. Per ulteriori informazioni su regole e query di sicurezza, consulta Informazioni sulla sicurezza per eseguire query sui dati.

Passaggi successivi