Google is committed to advancing racial equity for Black communities. See how.
Diese Seite wurde von der Cloud Translation API übersetzt.
Switch to English

Daten sicher abfragen

Diese Seite baut auf den Konzepten unter Strukturieren von Sicherheitsregeln und Schreiben von Bedingungen für Sicherheitsregeln auf, um zu erläutern, wie Cloud Firestore-Sicherheitsregeln mit Abfragen interagieren. Es wird genauer untersucht, wie sich Sicherheitsregeln auf die Abfragen auswirken, die Sie schreiben können, und es wird beschrieben, wie Sie sicherstellen, dass Ihre Abfragen dieselben Einschränkungen wie Ihre Sicherheitsregeln verwenden. Auf dieser Seite wird auch beschrieben, wie Sicherheitsregeln geschrieben werden, um Abfragen basierend auf Abfrageeigenschaften wie limit und orderBy zuzulassen oder orderBy .

Regeln sind keine Filter

Beachten Sie beim Schreiben von Abfragen zum Abrufen von Dokumenten, dass Sicherheitsregeln keine Filter sind - Abfragen sind alles oder nichts. Um Ihnen Zeit und Ressourcen zu sparen, bewertet Cloud Firestore eine Abfrage anhand ihrer potenziellen Ergebnismenge anstelle der tatsächlichen Feldwerte für alle Ihre Dokumente. Wenn eine Abfrage möglicherweise Dokumente zurückgibt, für die der Client keine Leseberechtigung hat, schlägt die gesamte Anforderung fehl.

Abfragen und Sicherheitsregeln

Wie die folgenden Beispiele zeigen, müssen Sie Ihre Abfragen so schreiben, dass sie den Einschränkungen Ihrer Sicherheitsregeln entsprechen.

Sichern und Abfragen von Dokumenten basierend auf auth.uid

Das folgende Beispiel zeigt, wie Sie eine Abfrage schreiben, um Dokumente abzurufen, die durch eine Sicherheitsregel geschützt sind. Stellen Sie sich eine Datenbank vor, die eine Sammlung von story Dokumenten enthält:

/ Geschichten / {storyid}

 {
  title: "A Great Story",
  content: "Once upon a time...",
  author: "some_auth_id",
  published: false
}
 

Zusätzlich zu den title und content speichert jedes Dokument den author und die published Felder, die für die Zugriffskontrolle verwendet werden sollen. In diesen Beispielen wird davon ausgegangen, dass die App die Firebase-Authentifizierung verwendet , um das author auf die UID des Benutzers festzulegen, der das Dokument erstellt hat. Die Firebase-Authentifizierung request.auth auch die Variable request.auth in den Sicherheitsregeln.

Die folgende Sicherheitsregel verwendet die Variablen request.auth und resource.data , um den Lese- und Schreibzugriff für jede story auf den Autor zu beschränken:

 service cloud.firestore {
  match /databases/{database}/documents {
    match /stories/{storyid} {
      // Only the authenticated user who authored the document can read or write
      allow read, write: if request.auth != null && request.auth.uid == resource.data.author;
    }
  }
}
 

Angenommen, Ihre App enthält eine Seite, auf der dem Benutzer eine Liste der von ihm erstellten story Dokumente angezeigt wird. Sie können davon ausgehen, dass Sie die folgende Abfrage verwenden können, um diese Seite zu füllen. Diese Abfrage schlägt jedoch fehl, da sie nicht dieselben Einschränkungen wie Ihre Sicherheitsregeln enthält:

Ungültig : Abfrageeinschränkungen stimmen nicht mit Sicherheitsregeleinschränkungen überein

 // This query will fail
db.collection("stories").get()
 

Die Abfrage schlägt auch dann fehl , wenn der aktuelle Benutzer tatsächlich der Autor jedes story Dokuments ist. Der Grund für dieses Verhalten liegt darin, dass Cloud Firestore beim Anwenden Ihrer Sicherheitsregeln die Abfrage anhand ihrer potenziellen Ergebnismenge und nicht anhand der tatsächlichen Eigenschaften von Dokumenten in Ihrer Datenbank bewertet. Wenn eine Abfrage möglicherweise Dokumente enthält, die gegen Ihre Sicherheitsregeln verstoßen, schlägt die Abfrage fehl.

Im Gegensatz dazu ist die folgende Abfrage erfolgreich, da sie dieselbe Einschränkung für das author wie die Sicherheitsregeln:

Gültig : Abfrageeinschränkungen stimmen mit Sicherheitsregeleinschränkungen überein

 var user = firebase.auth().currentUser;

db.collection("stories").where("author", "==", user.uid).get()
 

Sichern und Abfragen von Dokumenten basierend auf einem Feld

Um die Interaktion zwischen Abfragen und Regeln weiter zu demonstrieren, erweitern die folgenden Sicherheitsregeln den Lesezugriff für die stories , damit jeder Benutzer story Dokumente lesen kann, bei denen das published Feld auf true .

 service cloud.firestore {
  match /databases/{database}/documents {
    match /stories/{storyid} {
      // Anyone can read a published story; only story authors can read unpublished stories
      allow read: if resource.data.published == true || (request.auth != null && request.auth.uid == resource.data.author);
      // Only story authors can write
      allow write: if request.auth != null && request.auth.uid == resource.data.author;
    }
  }
}
 

Die Abfrage für veröffentlichte Seiten muss dieselben Einschränkungen wie die Sicherheitsregeln enthalten:

 db.collection("stories").where("published", "==", true).get()
 

Die Abfrageeinschränkung .where("published", "==", true) garantiert, dass resource.data.published für jedes Ergebnis true ist. Daher erfüllt diese Abfrage die Sicherheitsregeln und darf Daten lesen.

in und array-contains-any Abfragen

Wenn eine Auswertung in oder array-contains-any query Klausel gegen eine ruleset wertet Wolke Firestor jeweils getrennt Vergleichswert. Jeder Vergleichswert muss die Sicherheitsregeleinschränkungen erfüllen. Zum Beispiel für die folgende Regel:

 match /mydocuments/{doc} {
  allow read: if resource.data.x > 5;
}
 

Ungültig : Die Abfrage garantiert nicht, dass x > 5 für alle potenziellen Dokumente ist

 // This query will fail
db.collection("mydocuments").where("x", "in", [1, 3, 6, 42, 99]).get()
 

Gültig : Die Abfrage garantiert, dass x > 5 für alle potenziellen Dokumente ist

 db.collection("mydocuments").where("x", "in", [6, 42, 99, 105, 200]).get()
 

Auswerten von Einschränkungen für Abfragen

Ihre Sicherheitsregeln können auch Abfragen aufgrund ihrer Einschränkungen akzeptieren oder ablehnen. Die Variable request.query enthält die Eigenschaften limit , offset und orderBy einer Abfrage. Beispielsweise können Ihre Sicherheitsregeln jede Abfrage ablehnen, die die maximale Anzahl der abgerufenen Dokumente nicht auf einen bestimmten Bereich beschränkt:

 allow list: if request.query.limit <= 10;
 

Der folgende Regelsatz zeigt, wie Sicherheitsregeln geschrieben werden, mit denen Einschränkungen für Abfragen bewertet werden. In diesem Beispiel wird der Regelsatz für vorherige stories um die folgenden Änderungen erweitert:

  • Der Regelsatz unterteilt die Leseregel in Regeln für get und list .
  • Die get Regel beschränkt das Abrufen einzelner Dokumente auf öffentliche Dokumente oder Dokumente, die der Benutzer erstellt hat.
  • Die list wendet dieselben Einschränkungen wie get jedoch für Abfragen. Es überprüft auch das Abfragelimit und lehnt dann jede Abfrage ohne Limit oder mit einem Limit größer als 10 ab.
  • Der Regelsatz definiert eine authorOrPublished() Funktion, um Codeduplizierungen zu vermeiden.
 service cloud.firestore {

  match /databases/{database}/documents {

    match /stories/{storyid} {

      // Returns `true` if the requested story is 'published'
      // or the user authored the story
      function authorOrPublished() {
        return resource.data.published == true || request.auth.uid == resource.data.author;
      }

      // Deny any query not limited to 10 or fewer documents
      // Anyone can query published stories
      // Authors can query their unpublished stories
      allow list: if request.query.limit <= 10 &&
                     authorOrPublished();

      // Anyone can retrieve a published story
      // Only a story's author can retrieve an unpublished story
      allow get: if authorOrPublished();

      // Only a story's author can write to a story
      allow write: if request.auth.uid == resource.data.author;
    }

  }
}
 

Sammlungsgruppenabfragen und Sicherheitsregeln

Standardmäßig sind Abfragen auf eine einzelne Sammlung beschränkt und rufen nur Ergebnisse aus dieser Sammlung ab. Mit Sammlungsgruppenabfragen können Sie Ergebnisse aus einer Sammlungsgruppe abrufen, die aus allen Sammlungen mit derselben ID besteht. In diesem Abschnitt wird beschrieben, wie Sie Ihre Sammlungsgruppenabfragen mithilfe von Sicherheitsregeln sichern.

Sichern und Abfragen von Dokumenten basierend auf Sammlungsgruppen

In Ihren Sicherheitsregeln müssen Sie Abfragen von Sammlungsgruppen explizit zulassen, indem Sie eine Regel für die Sammlungsgruppe schreiben:

  1. rules_version = '2'; Sie sicher, dass rules_version = '2'; ist die erste Zeile Ihres Regelsatzes. Sammlungsgruppenabfragen erfordern das neue rekursive Platzhalterverhalten {name=**} der Sicherheitsregeln Version 2.
  2. Schreiben Sie eine Regel für Ihre Sammlungsgruppe mit match /{path=**}/ [COLLECTION_ID] /{doc} .

posts Sie sich beispielsweise ein Forum vor, das in forum organisiert ist forum die Untersammlungen von posts enthalten:

/ forums / {forumid} / posts / {postid}

 {
  author: "some_auth_id",
  authorname: "some_username",
  content: "I just read a great story.",
}
 

In dieser Anwendung machen wir Beiträge für ihre Eigentümer bearbeitbar und für authentifizierte Benutzer lesbar:

 service cloud.firestore {
  match /databases/{database}/documents {
    match /forums/{forumid}/posts/{post} {
      // Only authenticated users can read
      allow read: if request.auth != null;
      // Only the post author can write
      allow write: if request.auth != null && request.auth.uid == resource.data.author;
    }
  }
}
 

Jeder authentifizierte Benutzer kann die Beiträge eines einzelnen Forums abrufen:

 db.collection("forums/technology/posts").get()
 

Aber was ist, wenn Sie dem aktuellen Benutzer seine Beiträge in allen Foren anzeigen möchten? Sie können eine Sammlungsgruppenabfrage verwenden , um Ergebnisse aus allen posts abzurufen:

 var user = firebase.auth().currentUser;

db.collectionGroup("posts").where("author", "==", user.uid).get()
 

In Ihren Sicherheitsregeln müssen Sie diese Abfrage zulassen, indem Sie eine Lese- oder Listenregel für die posts schreiben:

 rules_version = '2';
service cloud.firestore {

  match /databases/{database}/documents {
    // Authenticated users can query the posts collection group
    // Applies to collection queries, collection group queries, and
    // single document retrievals
    match /{path=**}/posts/{post} {
      allow read: if request.auth != null;
    }
    match /forums/{forumid}/posts/{postid} {
      // Only a post's author can write to a post
      allow write: if request.auth != null && request.auth.uid == resource.data.author;

    }
  }
}
 

Beachten Sie jedoch, dass diese Regeln unabhängig von der Hierarchie für alle Sammlungen mit ID- posts gelten. Diese Regeln gelten beispielsweise für alle folgenden posts :

  • /posts/{postid}
  • /forums/{forumid}/posts/{postid}
  • /forums/{forumid}/subforum/{subforumid}/posts/{postid}

Sichere Sammlungsgruppenabfragen basierend auf einem Feld

Wie Abfragen mit nur einer Sammlung müssen auch Abfragen von Sammlungsgruppen die in Ihren Sicherheitsregeln festgelegten Einschränkungen erfüllen. Zum Beispiel können wir jedem Forumsbeitrag ein published Feld hinzufügen, wie wir es im obigen Beispiel für stories getan haben:

/ forums / {forumid} / posts / {postid}

 {
  author: "some_auth_id",
  authorname: "some_username",
  content: "I just read a great story.",
  published: false
}
 

Wir können dann schreiben Regeln für die posts Sammelgruppe auf der Basis published Status und der Post author :

 rules_version = '2';
service cloud.firestore {

  match /databases/{database}/documents {

    // Returns `true` if the requested post is 'published'
    // or the user authored the post
    function authorOrPublished() {
      return resource.data.published == true || request.auth.uid == resource.data.author;
    }

    match /{path=**}/posts/{post} {

      // Anyone can query published posts
      // Authors can query their unpublished posts
      allow list: if authorOrPublished();

      // Anyone can retrieve a published post
      // Authors can retrieve an unpublished post
      allow get: if authorOrPublished();
    }

    match /forums/{forumid}/posts/{postid} {
      // Only a post's author can write to a post
      allow write: if request.auth.uid == resource.data.author;
    }
  }
}
 

Mit diesen Regeln können Web-, iOS- und Android-Clients die folgenden Abfragen durchführen:

  • Jeder kann veröffentlichte Beiträge in einem Forum abrufen:

     db.collection("forums/technology/posts").where('published', '==', true).get()
     
  • Jeder kann die veröffentlichten Beiträge eines Autors in allen Foren abrufen:

     db.collectionGroup("posts").where("author", "==", "some_auth_id").where('published', '==', true).get()
     
  • Autoren können alle veröffentlichten und unveröffentlichten Beiträge in allen Foren abrufen:

     var user = firebase.auth().currentUser;
    
    db.collectionGroup("posts").where("author", "==", user.uid).get()
     

Sichern und Abfragen von Dokumenten basierend auf Sammlungsgruppe und Dokumentpfad

In einigen Fällen möchten Sie möglicherweise Sammlungsgruppenabfragen basierend auf dem Dokumentpfad einschränken. Um diese Einschränkungen zu erstellen, können Sie dieselben Techniken zum Sichern und Abfragen von Dokumenten basierend auf einem Feld verwenden.

Stellen Sie sich eine Anwendung vor, die die Transaktionen jedes Benutzers zwischen mehreren Börsen für Aktien und Kryptowährungen verfolgt:

/ users / {userid} / exchange / {exchangeid} / transaction / {transaction}

 {
  amount: 100,
  exchange: 'some_exchange_name',
  timestamp: April 1, 2019 at 12:00:00 PM UTC-7,
  user: "some_auth_id",
}
 

Beachten Sie das user . Obwohl wir aus dem Pfad des Dokuments wissen, welcher Benutzer ein transaction besitzt, duplizieren wir diese Informationen in jedem transaction , da wir damit zwei Dinge tun können:

  • Schreiben Sie Sammlungsgruppenabfragen, die auf Dokumente beschränkt sind, deren Dokumentpfad eine bestimmte /users/{userid} . Beispielsweise:

     var user = firebase.auth().currentUser;
    // Return current user's last five transactions across all exchanges
    db.collectionGroup("transactions").where("user", "==", user).orderBy('timestamp').limit(5)
     
  • Erzwingen diese Einschränkung für alle Abfragen auf der transactions Sammelgruppe so ein Benutzer einen anderen Benutzer nicht abrufen können , transaction

Wir setzen diese Einschränkung in unseren Sicherheitsregeln durch und schließen die Datenvalidierung für das user ein:

 rules_version = '2';
service cloud.firestore {

  match /databases/{database}/documents {

    match /{path=**}/transactions/{transaction} {
      // Authenticated users can retrieve only their own transactions
      allow read: if resource.data.user == request.auth.uid;
    }

    match /users/{userid}/exchange/{exchangeid}/transactions/{transaction} {
      // Authenticated users can write to their own transactions subcollections
      // Writes must populate the user field with the correct auth id
      allow write: if userid == request.auth.uid && request.data.user == request.auth.uid
    }
  }
}
 

Nächste Schritte