Struktursicherheitsregeln

Firestore-Sicherheitsregeln geben Ihnen die Möglichkeit, den Zugriff auf Dokumente und Sammlungen in Ihrer Datenbank zu steuern. Mit der flexiblen Regelsyntax können Sie Regeln für beliebige Bereiche erstellen – von sämtlichen Schreibvorgängen über die gesamte Datenbank bis hin zu Vorgängen in einem bestimmten Dokument.

In diesem Leitfaden werden die grundlegende Syntax und die Struktur von Sicherheitsregeln erläutert. Kombinieren Sie diese Syntax mit Bedingungen für Sicherheitsregeln, um vollständige Regelsätze zu erstellen.

Dienste und Datenbanken deklarieren

Firestore-Sicherheitsregeln beginnen immer mit der folgenden Deklaration:

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

Die Deklaration service cloud.firestore weist die Regeln Firestore zu und verhindert Konflikte zwischen Firestore-Sicherheitsregeln und Regeln für andere Produkte wie Cloud Storage.

Die Deklaration match /databases/{database}/documents gibt an, dass die Regeln für jede Firestore-Datenbank im Projekt eingehalten werden müssen. Aktuell enthält jedes Projekt nur eine einzige Datenbank mit dem Namen (default).

Grundlegende Lese-/Schreibregeln

Grundlegende Regeln bestehen aus einer match-Anweisung, die einen Dokumentpfad angibt, und einem allow-Ausdruck, der festlegt, wann das Lesen der angegebenen Daten erlaubt ist:

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

Alle Match-Anweisungen sollten auf Dokumente und nicht auf Sammlungen verweisen. Eine Match-Anweisung kann auf ein bestimmtes Dokument verweisen, z. B. in match /cities/SF, oder Platzhalter verwenden, um auf ein beliebiges Dokument im angegebenen Pfad zu verweisen, z. B. in match /cities/{city}.

In dem Beispiel oben verwendet die Match-Anweisung die Platzhaltersyntax {city}. Das bedeutet, dass die Regel für alle Dokumente in der Sammlung cities gilt, z. B. für /cities/SF oder /cities/NYC . Wenn die allow-Ausdrücke in der Match-Anweisung ausgewertet werden, wird die city-Variable in den Namen des Stadtdokuments aufgelöst, z. B. SF oder NYC .

Detaillierte Vorgänge

In manchen Fällen ist es sinnvoll, read und write in detailliertere Vorgänge zu untergliedern. Möglicherweise möchte Ihre Anwendung bei der Erstellung von Dokumenten andere Bedingungen erzwingen als beim Löschen von Dokumenten. Sie können auch Lesevorgänge einzelner Dokumente erlauben, aber große Abfragen ablehnen.

Eine read-Regel kann in get und list untergliedert werden, während eine write-Regel in create, update und delete untergliedert werden kann:

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

Hierarchische Daten

Daten in Firestore sind in Sammlungen von Dokumenten organisiert. Jedes Dokument kann die entsprechende Hierarchie durch untergeordnete Sammlungen (Untersammlungen) erweitern. Für die Nutzung der Hierarchie ist es wichtig zu verstehen, wie Sicherheitsregeln mit hierarchischen Daten interagieren.

Betrachten Sie die Situation, in der jedes Dokument in der Sammlung cities eine Untersammlung landmarks enthält. Sicherheitsregeln gelten nur für den übereinstimmenden Pfad. Daher gelten die in der Sammlung cities definierten Zugriffssteuerungen nicht für die Untersammlung landmarks. Um den Zugriff auf untergeordnete Sammlungen zu steuern, müssen Sie stattdessen explizite Regeln schreiben:

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

Beim Verschachteln von match-Anweisungen bezieht sich der Pfad der inneren match-Anweisung immer auf den Pfad der äußeren match-Anweisung. Die folgenden Regelsätze sind daher äquivalent:

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

Rekursive Platzhalter

Wenn Regeln auf eine beliebig tiefe Hierarchie angewendet werden sollen, verwenden Sie die rekursive Platzhaltersyntax {name=**}. Beispiel:

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

Bei Verwendung der rekursiven Platzhaltersyntax enthält die Platzhaltervariable das gesamte übereinstimmende Pfadsegment, auch wenn sich das Dokument in einer tief verschachtelten Untersammlung befindet. Die oben aufgeführten Regeln würden beispielsweise mit einem Dokument unter /cities/SF/landmarks/coit_tower übereinstimmen und der Wert der document-Variable wäre SF/landmarks/coit_tower.

Beachten Sie jedoch, dass das Verhalten rekursiver Platzhalter von der Regelversion abhängt.

Version 1

Sicherheitsregeln verwenden standardmäßig Version 1. In Version 1 entsprechen rekursive Platzhalter einem oder mehreren Pfadelementen. Sie stimmen nicht mit einem leeren Pfad überein. match /cities/{city}/{document=**} entspricht also Dokumenten in Untersammlungen, aber nicht mit Dokumenten in der Sammlung cities überein. Dagegen stimmt match /cities/{document=**} mit beiden Dokumenten in der Sammlung cities und mit Untersammlungen überein.

Rekursive Platzhalter müssen am Ende einer Match-Anweisung stehen.

Version 2

In Version 2 der Sicherheitsregeln entsprechen rekursive Platzhalter null oder mehr Pfadelementen. match/cities/{city}/{document=**} stimmt mit Dokumenten in allen Untersammlungen sowie mit Dokumenten in der Sammlung cities überein.

Sie müssen die Version 2 aktivieren, indem Sie rules_version = '2'; oben in Ihren Sicherheitsregeln hinzufügen:

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

Sie können höchstens einen rekursiven Platzhalter pro Match-Anweisung haben, aber in Version 2 können Sie diesen Platzhalter überall in der Match-Anweisung platzieren. Beispiel:

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

Wenn Sie Abfragen von Sammlungsgruppen verwenden, müssen Sie die Version 2 verwenden, siehe Abfragen von Sammlungsgruppen schützen.

Überlappende Match-Anweisungen

Es ist möglich, dass ein Dokument mit mehr als einer match-Anweisung übereinstimmt. Falls mehrere allow-Ausdrücke mit einer Anfrage übereinstimmen, wird der Zugriff erlaubt, wenneine der Bedingungen true ist:

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

Im oberen Beispiel werden alle Lese- und Schreibzugriffe auf die Sammlung cities erlaubt, weil die zweite Regel immer true ist, obwohl die erste Regel immer false ist.

Beschränkungen für Sicherheitsregeln

Beachten Sie bei der Arbeit mit Sicherheitsregeln die folgenden Beschränkungen:

Limit Details
Maximale Anzahl exists()-, get()- und getAfter()-Aufrufe pro Anfrage
  • 10 für Einzeldokumentanfragen und Abfrage-Anfragen.
  • 20 für Lesevorgänge, Transaktionen und Batch-Schreibvorgänge für mehrere Dokumente. Das vorherige Limit von 10 gilt auch für jeden Vorgang.

    Angenommen, Sie erstellen eine Batch-Schreibanfrage mit 3 Schreibvorgängen und Ihre Sicherheitsregeln verwenden 2 Dokumentzugriffsaufrufe, um jeden Schreibvorgang zu validieren. In diesem Fall verwendet jeder Schreibvorgang 2 von seinen 10 Zugriffsaufrufen und die Batch-Schreibanfrage 6 von ihren 20 Zugriffsaufrufen.

Das Überschreiten eines dieser Limits führt zu einem Fehler mit Berechtigungsverweigerung.

Einige Dokumentzugriffsaufrufe können zwischengespeichert werden. Zwischengespeicherte Aufrufe werden nicht in die Limits einberechnet.

Maximale Tiefe verschachtelter match-Anweisungen 10
Maximale Pfadlänge in Pfadsegmenten, die innerhalb eines Satzes von verschachtelten match-Anweisungen zulässig ist 100
Maximale Anzahl Pfaderfassungsvariablen, die in einem Satz verschachtelter match-Anweisungen zulässig ist 20
Maximale Funktionsaufruftiefe 20
Maximale Anzahl Funktionsargumente 7
Maximale Anzahl let-Variablenbindungen pro Funktion 10
Maximale Anzahl rekursiver oder zyklischer Funktionsaufrufe 0 (nicht zulässig)
Maximale Anzahl bewerteter Ausdrücke pro Anfrage 1.000
Maximale Größe eines Regelsatzes Regelsätze müssen zwei Größenbeschränkungen einhalten:
  • Ein Limit von 256 KB für die Größe der Regelsatztextquelle, die über die Firebase Console oder die Befehlszeile mit firebase deploy veröffentlicht wird.
  • Ein Limit von 250 KB für die Größe des kompilierten Regelsatzes, der entsteht, wenn Firebase die Quelle verarbeitet und im Back-End aktiviert.

Nächste Schritte