Check out what’s new from Firebase@ Google I/O 2021, and join our alpha program for early access to the new Remote Config personalization feature. Learn more

Bedingungen für Cloud Firestore-Sicherheitsregeln schreiben

Dieser Leitfaden baut auf dem Leitfaden zur Strukturierung von Sicherheitsregeln auf, um zu zeigen, wie Sie Ihren Cloud Firestore-Sicherheitsregeln Bedingungen hinzufügen. Wenn Sie mit den Grundlagen der Cloud Firestore-Sicherheitsregeln nicht vertraut sind, lesen Sie den Leitfaden für die ersten Schritte .

Der primäre Baustein der Cloud Firestore-Sicherheitsregeln ist die Bedingung. Eine Bedingung ist ein boolescher Ausdruck, der bestimmt, ob eine bestimmte Operation zugelassen oder abgelehnt werden soll. Verwenden Sie Sicherheitsregeln, um Bedingungen zu schreiben, die die Benutzerauthentifizierung überprüfen, eingehende Daten validieren oder sogar auf andere Teile Ihrer Datenbank zugreifen.

Authentifizierung

Eines der gängigsten Sicherheitsregelmuster ist die Zugriffssteuerung basierend auf dem Authentifizierungsstatus des Benutzers. Ihre App möchte beispielsweise nur angemeldeten Benutzern erlauben, Daten zu schreiben:

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

Ein weiteres gängiges Muster besteht darin, sicherzustellen, dass Benutzer nur ihre eigenen Daten lesen und schreiben können:

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

Wenn Ihre Anwendung Firebase Authentication oder Google Cloud Identity Platform verwendet , enthält die Variable request.auth die Authentifizierungsinformationen für den Client, der Daten anfordert. Weitere Informationen zu request.auth finden Sie in der Referenzdokumentation .

Datenvalidierung

Viele Apps speichern Zugriffskontrollinformationen als Felder in Dokumenten in der Datenbank. Cloud Firestore-Sicherheitsregeln können den Zugriff basierend auf Dokumentdaten dynamisch zulassen oder verweigern:

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

Die resource verweist auf das angeforderte Dokument, und resource.data ist eine Zuordnung aller im Dokument gespeicherten Felder und Werte. Weitere Informationen zur resource finden Sie in der Referenzdokumentation .

Beim Schreiben von Daten möchten Sie möglicherweise eingehende Daten mit vorhandenen Daten vergleichen. Wenn Ihr Regelsatz in diesem Fall das ausstehende Schreiben request.resource , enthält die Variable request.resource den zukünftigen Status des Dokuments. Bei update , die nur eine Teilmenge der Dokumentfelder request.resource , enthält die Variable request.resource den request.resource des ausstehenden Dokuments nach der Operation. Sie können die Feldwerte in request.resource , um unerwünschte oder inkonsistente request.resource zu verhindern:

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

Auf andere Dokumente zugreifen

Mit den Funktionen get() und exists() können Ihre Sicherheitsregeln eingehende Anfragen mit anderen Dokumenten in der Datenbank vergleichen. Die Funktionen get() und exists() erwarten beide vollständig angegebene Dokumentpfade. Wenn Sie Variablen verwenden, um Pfade für get() und exists() zu konstruieren, müssen Sie Variablen explizit mit der Syntax $(variable) maskieren.

Im folgenden Beispiel wird die database von der Match-Anweisung match /databases/{database}/documents und zur Bildung des Pfads verwendet:

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

Für Schreibvorgänge können Sie die Funktion getAfter() verwenden, um auf den Status eines Dokuments zuzugreifen, nachdem eine Transaktion oder ein Stapel von Schreibvorgängen abgeschlossen wurde, aber bevor die Transaktion oder der Stapel festgeschrieben werden. Wie get() die Funktion getAfter() einen vollständig angegebenen Dokumentpfad. Sie können getAfter() , um Sätze von Schreibvorgängen zu definieren, die zusammen als Transaktion oder Batch erfolgen müssen.

Auf Anruflimits zugreifen

Es gibt ein Limit für Dokumentzugriffsaufrufe pro Regelsatzauswertung:

  • 10 für Einzeldokumentanforderungen und Abfrageanforderungen.
  • 20 für Multi-Dokument-Lesevorgänge, Transaktionen und Schreibvorgänge im Stapel. Die bisherige Grenze von 10 gilt auch für jeden Vorgang.

    Stellen Sie sich beispielsweise vor, Sie erstellen eine Batch-Schreibanforderung mit 3 Schreibvorgängen und Ihre Sicherheitsregeln verwenden 2 Dokumentzugriffsaufrufe, um jeden Schreibvorgang zu validieren. In diesem Fall verwendet jeder Schreibvorgang 2 seiner 10 Zugriffsaufrufe und die gestapelte Schreibanforderung verwendet 6 seiner 20 Zugriffsaufrufe.

Das Überschreiten eines der Grenzwerte führt zu einem Berechtigungsverweigerungsfehler. Einige Dokumentzugriffsaufrufe können zwischengespeichert werden, und zwischengespeicherte Aufrufe zählen nicht zu den Grenzwerten.

Ausführliche Erläuterungen dazu, wie sich diese Beschränkungen auf Transaktionen und Schreibvorgänge im Stapel auswirken, finden Sie im Handbuch zum Sichern atomarer Operationen .

Zugriff auf Anrufe und Preise

Die Verwendung dieser Funktionen führt einen Lesevorgang in Ihrer Datenbank aus, dh das Lesen von Dokumenten wird Ihnen auch dann in Rechnung gestellt, wenn Ihre Regeln die Anforderung ablehnen. Genauere Abrechnungsinformationen finden Sie unter Cloud Firestore-Preise .

Benutzerdefinierte Funktionen

Wenn Ihre Sicherheitsregeln komplexer werden, möchten Sie möglicherweise Bedingungssätze in Funktionen einschließen, die Sie in Ihrem Regelsatz wiederverwenden können. Sicherheitsregeln unterstützen benutzerdefinierte Funktionen. Die Syntax für benutzerdefinierte Funktionen ähnelt ein wenig JavaScript, aber Sicherheitsregelfunktionen sind in einer domänenspezifischen Sprache geschrieben, die einige wichtige Einschränkungen aufweist:

  • Funktionen können nur eine einzige return Anweisung enthalten. Sie können keine zusätzliche Logik enthalten. Sie können beispielsweise keine Schleifen ausführen oder externe Dienste aufrufen.
  • Funktionen können automatisch auf Funktionen und Variablen aus dem Bereich zugreifen, in dem sie definiert sind. Beispielsweise hat eine im service cloud.firestore definierte Funktion Zugriff auf die resource und integrierte Funktionen wie get() und exists() .
  • Funktionen können andere Funktionen aufrufen, aber nicht rekursiv sein. Die Gesamttiefe der Aufrufliste ist auf 10 begrenzt.
  • In Rules Version v2 können Funktionen Variablen mit dem Schlüsselwort let definieren. Funktionen können bis zu 10 let-Bindungen haben, müssen jedoch mit einer return-Anweisung enden.

Eine Funktion wird mit dem definierten function Schlüsselwort und nimmt null oder mehr Argumente. Sie können beispielsweise die beiden in den obigen Beispielen verwendeten Bedingungstypen in einer einzigen Funktion kombinieren:

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

Durch die Verwendung von Funktionen in Ihren Sicherheitsregeln werden diese mit zunehmender Komplexität Ihrer Regeln leichter wartbar.

Regeln sind keine Filter

Wenn Sie Ihre Daten sichern und mit dem Schreiben von Abfragen beginnen, denken Sie daran, dass Sicherheitsregeln keine Filter sind. Sie können keine Abfrage für alle Dokumente in einer Sammlung schreiben und erwarten, dass Cloud Firestore nur die Dokumente zurückgibt, auf die der aktuelle Client Zugriff hat.

Nehmen Sie zum Beispiel die folgende Sicherheitsregel:

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

Abgelehnt : Diese Regel lehnt die folgende Abfrage ab, da die Ergebnismenge Dokumente enthalten kann, deren visibility nicht public :

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

Zulässig : Diese Regel lässt die folgende Abfrage zu, da die where("visibility", "==", "public") Klausel garantiert, dass die Ergebnismenge die Regelbedingung erfüllt:

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

Cloud Firestore-Sicherheitsregeln werten jede Abfrage anhand ihres potenziellen Ergebnisses aus und schlagen die Anforderung fehl, wenn ein Dokument zurückgegeben werden könnte, für das der Client keine Leseberechtigung hat. Abfragen müssen den Einschränkungen Ihrer Sicherheitsregeln entsprechen. Weitere Informationen zu Sicherheitsregeln und Abfragen finden Sie unter Sicheres Abfragen von Daten .

Nächste Schritte