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

Sprache der Sicherheitsregeln

Firebase-Sicherheitsregeln nutzen flexible, leistungsstarke, benutzerdefinierte Sprachen, die ein breites Spektrum an Komplexität und Granularität unterstützen. Sie können Ihre Regeln so spezifisch oder allgemein gestalten, wie es für Ihre App sinnvoll ist. Echtzeitdatenbankregeln verwenden eine Syntax, die wie JavaScript in einer JSON-Struktur aussieht. Cloud Firestor und Cloud Storage Regeln verwenden , um eine Sprache auf der Grundlage der gemeinsamen Expression Language (CEL) , die mit auf CEL baut match und allow Aussagen , dass die Unterstützung Zugang bedingt gewährt.

Da es sich jedoch um benutzerdefinierte Sprachen handelt, gibt es eine Lernkurve. Verwenden Sie diesen Leitfaden, um die Regelsprache besser zu verstehen, während Sie tiefer in komplexere Regeln eintauchen.

Wählen Sie ein Produkt aus, um mehr über seine Regeln zu erfahren.

Grundstruktur

Cloud Firestore

Firebase-Sicherheitsregeln in Cloud Firestore und Cloud Storage verwenden die folgende Struktur und Syntax:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

Es ist wichtig, die folgenden Schlüsselkonzepte zu verstehen, wenn Sie die Regeln erstellen:

  • Request: Die Methode oder Methoden, die in der allow Anweisung aufgerufen werden. Dies sind Methoden, die Sie ausführen dürfen. Die Standardmethoden sind: get , list , create , update und delete . Die bequemen read und write ermöglichen einen breiten Lese- und Schreibzugriff auf die angegebene Datenbank oder den angegebenen Speicherpfad.
  • Pfad: Die Datenbank oder der Speicherort, dargestellt als URI-Pfad.
  • Regel: Die allow Anweisung, die eine Bedingung enthält, die eine Anforderung zulässt, wenn sie als wahr ausgewertet wird.

Jedes dieser Konzepte wird unten ausführlicher beschrieben.

Cloud-Speicher

Firebase-Sicherheitsregeln in Cloud Firestore und Cloud Storage verwenden die folgende Struktur und Syntax:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

Es ist wichtig, die folgenden Schlüsselkonzepte beim Erstellen der Regeln zu verstehen:

  • Request: Die Methode oder Methoden, die in der allow Anweisung aufgerufen wurden. Dies sind Methoden, die Sie ausführen dürfen. Die Standardmethoden sind: get , list , create , update und delete . Die bequemen read und write ermöglichen einen breiten Lese- und Schreibzugriff auf die angegebene Datenbank oder den angegebenen Speicherpfad.
  • Pfad: Die Datenbank oder der Speicherort, dargestellt als URI-Pfad.
  • Regel: Die allow Anweisung, die eine Bedingung enthält, die eine Anforderung zulässt, wenn sie als wahr ausgewertet wird.

Jedes dieser Konzepte wird unten ausführlicher beschrieben.

Echtzeit-Datenbank

In Realtime Database bestehen Firebase-Sicherheitsregeln aus JavaScript-ähnlichen Ausdrücken, die in einem JSON-Dokument enthalten sind.

Sie verwenden die folgende Syntax:

{
  "rules": {
    "<<path>>": {
    // Allow the request if the condition for each method is true.
      ".read": <<condition>>,
      ".write": <<condition>>,
      ".validate": <<condition>>
    }
  }
}

Es gibt drei grundlegende Elemente in der Regel:

  • Pfad: Der Speicherort der Datenbank. Dies spiegelt die JSON-Struktur Ihrer Datenbank wider.
  • Request: Dies sind die Methoden, die die Regel verwendet, um den Zugriff zu gewähren. Die read und write gewähren umfassenden Lese- und Schreibzugriff, während validate als sekundäre Überprüfung dienen, um den Zugriff basierend auf eingehenden oder vorhandenen Daten zu gewähren.
  • Bedingung: Die Bedingung, die eine Anforderung zulässt, wenn sie als wahr ausgewertet wird.

Regelkonstrukte

Cloud Firestore

Die grundlegenden Elemente einer Regel in Cloud Firestore und Cloud Storage lauten wie folgt:

  • Die service : Deklariert das Firebase-Produkt, für das die Regeln gelten.
  • Der match Block: Definiert einen Pfad in der Datenbank oder im Storage-Bucket, für den die Regeln gelten.
  • Die allow Anweisung: Stellt Bedingungen für die Gewährung des Zugriffs, differenziert nach Methoden, bereit. Zu den unterstützten Methoden gehören: get , list , create , update , delete und die praktischen Methoden read und write .
  • Optionale function : Bieten die Möglichkeit, Bedingungen für die Verwendung über mehrere Regeln hinweg zu kombinieren und zu umschließen.

Der service enthält einen oder mehrere match mit allow Anweisungen, die Bedingungen bereitstellen, die den Zugriff auf Anforderungen gewähren. Die request und resource stehen zur Verwendung in Regelbedingungen zur Verfügung. Die Sprache der Firebase-Sicherheitsregeln unterstützt auch function .

Syntaxversion

Die syntax gibt die Version der Firebase Rules-Sprache an, die zum Schreiben der Quelle verwendet wurde. Die neueste Version der Sprache ist v2 .

rules_version = '2';
service cloud.firestore {
...
}

Wenn keine Anweisung rules_version wird, werden Ihre Regeln mit der v1 Engine ausgewertet.

Bedienung

Die service - Erklärung definiert , welche Firebase Produkt oder eine Dienstleistung, Ihre Regeln anzuwenden. Sie können nur eine service Deklaration pro Quelldatei einschließen.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Cloud-Speicher

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

Wenn Sie Regeln für Cloud Firestore und Cloud Storage mit der Firebase-Befehlszeile definieren, müssen Sie diese in separaten Dateien verwalten.

Spiel

Ein match Block deklariert einen path , das gegenüber dem Pfad für die angeforderte Operation abgestimmt ist (die ankommende request.path ). Der Hauptteil der match muss einen oder mehrere verschachtelte match , allow Anweisungen oder function . Der Pfad in verschachtelten match Blöcken ist relativ zum Pfad im übergeordneten match Block.

Der path Muster ist ein Verzeichnis-wie Name, Variablen oder Platzhalter enthalten kann. Der path Muster ermöglicht Single-Pfad - Segment und Multi-Pfad - Segment Streichhölzer. Alle in einen path gebundenen Variablen sind im match oder in jedem verschachtelten Bereich sichtbar, in dem der path deklariert ist.

Spiele gegen einen path Muster können teilweise oder vollständig sein:

  • Teilweise Übereinstimmung: Der path Muster ist ein Präfix-Match des request.path .
  • Vollständige Spiele: Der path Muster passt die gesamte request.path .

Bei einer vollständigen Übereinstimmung werden die Regeln innerhalb des Blocks ausgewertet. Wenn eine teilweise Übereinstimmung hergestellt wird, werden die verschachtelten match getestet, um zu sehen, ob ein verschachtelter path die Übereinstimmung vervollständigt .

Die Regeln in jeder vollständigen match werden ausgewertet, um zu bestimmen, ob die Anforderung zugelassen wird. Wenn eine übereinstimmende Regel den Zugriff gewährt, wird die Anforderung zugelassen. Wenn keine übereinstimmende Regel den Zugriff gewährt, wird die Anfrage abgelehnt.

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

Wie das obige Beispiel zeigt, sind die path unterstützt Erklärungen die folgenden Variablen:

  • Einzelsegment-Wildcard: Eine Platzhaltervariable wird in einem Pfad deklariert, indem eine Variable in geschweifte Klammern eingeschlossen wird: {variable} . Auf diese Variable kann innerhalb der match Anweisung als string .
  • Rekursiver Platzhalter: Der rekursive Platzhalter oder Multi-Segment-Platzhalter entspricht mehreren Pfadsegmenten an oder unter einem Pfad. Dieser Platzhalter entspricht allen Pfaden unterhalb des von Ihnen festgelegten Speicherorts. Sie können es deklarieren, indem Sie die Zeichenfolge =** am Ende Ihrer Segmentvariablen hinzufügen: {variable=**} . Auf diese Variable kann innerhalb der match Anweisung als path zugegriffen werden.

ermöglichen

Der match Block enthält eine oder mehrere allow Anweisungen. Dies sind Ihre tatsächlichen Regeln. Sie können sie bewerben allow Regeln Methoden auf eine oder mehr. Die Bedingungen einer allow müssen als wahr ausgewertet werden, damit Cloud Firestore oder Cloud Storage alle eingehenden Anfragen bewilligen können. Sie können auch allow Anweisungen ohne Bedingungen schreiben, z. B. allow read . Wenn die allow Anweisung jedoch keine Bedingung enthält, lässt sie immer die Anforderung für diese Methode zu.

Wenn eine der allow für die Methode erfüllt ist, wird die Anforderung zugelassen. Wenn eine umfassendere Regel den Zugriff gewährt, gewähren Regeln außerdem Zugriff und ignorieren alle detaillierteren Regeln, die den Zugriff einschränken könnten.

Betrachten Sie das folgende Beispiel, in dem jeder Benutzer seine eigenen Dateien lesen oder löschen kann. Eine genauere Regel lässt Schreibvorgänge nur zu, wenn der Benutzer, der den Schreibvorgang anfordert, Eigentümer der Datei ist und die Datei eine PNG-Datei ist. Ein Benutzer kann alle Dateien im Unterpfad löschen – auch wenn es sich nicht um PNGs handelt – weil die frühere Regel dies zulässt.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

Methode

Jede allow Anweisung enthält eine Methode, die den Zugriff für eingehende Anforderungen derselben Methode gewährt.

Methode Art der Anfrage
Komfortmethoden
read Jede Art von Leseanfrage
write Jede Art von Schreibanfrage
Standardmethoden
get Leseanfragen für einzelne Dokumente oder Dateien
list Leseanfragen für Abfragen und Sammlungen
create Neue Dokumente oder Dateien schreiben
update In vorhandene Dokumente oder Dateien schreiben
delete Daten löschen

Sie können Lesemethoden im selben match Block oder widersprüchliche Schreibmethoden in derselben path nicht überlappen.

Die folgenden Regeln würden beispielsweise fehlschlagen:

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

Funktion

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

Hier ist ein Beispiel, das Funktionsargumente und let-Zuweisungen zeigt. Zuweisungsanweisungen müssen durch Semikola getrennt werden.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

Beachten Sie, wie die isAdmin Zuweisung ein Nachschlagen der Admins-Sammlung erzwingt. Nutzen Sie für eine träge Auswertung ohne unnötige Nachschlagevorgänge die Kurzschlusseigenschaften von && (AND) und || (ODER) Vergleiche, um eine zweite Funktion nur isAuthor wenn isAuthor als wahr (für && Vergleiche) oder falsch (für || Vergleiche) isAuthor wird.

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

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

Cloud-Speicher

Die grundlegenden Elemente einer Regel in Cloud Firestore und Cloud Storage lauten wie folgt:

  • Die service : Deklariert das Firebase-Produkt, für das die Regeln gelten.
  • Der match Block: Definiert einen Pfad in der Datenbank oder im Storage-Bucket, für den die Regeln gelten.
  • Die allow Anweisung: Stellt Bedingungen für die Gewährung des Zugriffs, differenziert nach Methoden, bereit. Zu den unterstützten Methoden gehören: get , list , create , update , delete und die praktischen Methoden read und write .
  • Optionale function : Bieten die Möglichkeit, Bedingungen für die Verwendung über mehrere Regeln hinweg zu kombinieren und zu umschließen.

Der service enthält einen oder mehrere match mit allow Anweisungen, die Bedingungen bereitstellen, die den Zugriff auf Anforderungen gewähren. Die request und resource stehen zur Verwendung in Regelbedingungen zur Verfügung. Die Sprache der Firebase-Sicherheitsregeln unterstützt auch function .

Syntaxversion

Die syntax gibt die Version der Firebase Rules-Sprache an, die zum Schreiben der Quelle verwendet wurde. Die neueste Version der Sprache ist v2 .

rules_version = '2';
service cloud.firestore {
...
}

Wenn keine Anweisung rules_version wird, werden Ihre Regeln mit der v1 Engine ausgewertet.

Bedienung

Die service - Erklärung definiert , welche Firebase Produkt oder eine Dienstleistung, Ihre Regeln anzuwenden. Sie können nur eine service Deklaration pro Quelldatei einschließen.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Cloud-Speicher

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

Wenn Sie Regeln für Cloud Firestore und Cloud Storage mit der Firebase-CLI definieren, müssen Sie diese in separaten Dateien verwalten.

Spiel

Ein match Block deklariert einen path , das gegenüber dem Pfad für die angeforderte Operation abgestimmt ist (die ankommende request.path ). Der Hauptteil der match muss einen oder mehrere verschachtelte match , allow Anweisungen oder function . Der Pfad in verschachtelten match Blöcken ist relativ zum Pfad im übergeordneten match Block.

Der path Muster ist ein Verzeichnis-wie Name, Variablen oder Platzhalter enthalten kann. Der path Muster ermöglicht Single-Pfad - Segment und Multi-Pfad - Segment Streichhölzer. Alle in einen path gebundenen Variablen sind im match oder in jedem verschachtelten Bereich sichtbar, in dem der path deklariert ist.

Spiele gegen einen path Muster können teilweise oder vollständig sein:

  • Teilweise Übereinstimmung: Der path Muster ist ein Präfix-Match des request.path .
  • Vollständige Spiele: Der path Muster passt die gesamte request.path .

Bei einer vollständigen Übereinstimmung werden die Regeln innerhalb des Blocks ausgewertet. Wenn eine teilweise Übereinstimmung hergestellt wird, werden die verschachtelten match getestet, um zu sehen, ob ein verschachtelter path die Übereinstimmung vervollständigt .

Die Regeln in jeder vollständigen match werden ausgewertet, um zu bestimmen, ob die Anforderung zugelassen wird. Wenn eine übereinstimmende Regel den Zugriff gewährt, wird die Anforderung zugelassen. Wenn keine übereinstimmende Regel den Zugriff gewährt, wird die Anfrage abgelehnt.

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

Wie das obige Beispiel zeigt, sind die path unterstützt Erklärungen die folgenden Variablen:

  • Einzelsegment-Wildcard: Eine Platzhaltervariable wird in einem Pfad deklariert, indem eine Variable in geschweifte Klammern eingeschlossen wird: {variable} . Auf diese Variable kann innerhalb der match Anweisung als string .
  • Rekursiver Platzhalter: Der rekursive Platzhalter oder Multi-Segment-Platzhalter entspricht mehreren Pfadsegmenten an oder unter einem Pfad. Dieser Platzhalter entspricht allen Pfaden unterhalb des von Ihnen festgelegten Speicherorts. Sie können es deklarieren, indem Sie die Zeichenfolge =** am Ende Ihrer Segmentvariablen hinzufügen: {variable=**} . Auf diese Variable kann innerhalb der match Anweisung als path zugegriffen werden.

ermöglichen

Der match Block enthält eine oder mehrere allow Anweisungen. Dies sind Ihre tatsächlichen Regeln. Sie können sie bewerben allow Regeln Methoden auf eine oder mehr. Die Bedingungen für eine allow müssen als wahr ausgewertet werden, damit Cloud Firestore oder Cloud Storage alle eingehenden Anfragen erfüllen können. Sie können auch allow Anweisungen ohne Bedingungen schreiben, z. B. allow read . Wenn die allow Anweisung jedoch keine Bedingung enthält, lässt sie immer die Anforderung für diese Methode zu.

Wenn eine der allow für die Methode erfüllt ist, wird die Anforderung zugelassen. Wenn eine umfassendere Regel den Zugriff gewährt, gewähren Regeln außerdem Zugriff und ignorieren alle detaillierteren Regeln, die den Zugriff einschränken könnten.

Betrachten Sie das folgende Beispiel, in dem jeder Benutzer seine eigenen Dateien lesen oder löschen kann. Eine genauere Regel lässt Schreibvorgänge nur zu, wenn der Benutzer, der den Schreibvorgang anfordert, Eigentümer der Datei ist und die Datei eine PNG-Datei ist. Ein Benutzer kann alle Dateien im Unterpfad löschen – auch wenn es sich nicht um PNGs handelt – weil die frühere Regel dies zulässt.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

Methode

Jede allow Anweisung enthält eine Methode, die den Zugriff für eingehende Anforderungen derselben Methode gewährt.

Methode Art der Anfrage
Komfortmethoden
read Jede Art von Leseanfrage
write Jede Art von Schreibanfrage
Standardmethoden
get Leseanfragen für einzelne Dokumente oder Dateien
list Leseanfragen für Abfragen und Sammlungen
create Neue Dokumente oder Dateien schreiben
update In vorhandene Dokumente oder Dateien schreiben
delete Daten löschen

Sie können Lesemethoden im selben match Block oder widersprüchliche Schreibmethoden in derselben path nicht überlappen.

Die folgenden Regeln würden beispielsweise fehlschlagen:

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

Funktion

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

Hier ist ein Beispiel, das Funktionsargumente und let-Zuweisungen zeigt. Let-Zuweisungsanweisungen müssen durch Semikola getrennt werden.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

Beachten Sie, wie die isAdmin Zuweisung ein Nachschlagen der Admins-Sammlung erzwingt. Nutzen Sie für eine träge Auswertung ohne unnötige Nachschlagevorgänge die Kurzschlusseigenschaften von && (AND) und || (ODER) Vergleiche, um eine zweite Funktion nur isAuthor wenn isAuthor als wahr (für && Vergleiche) oder falsch (für || Vergleiche) isAuthor wird.

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

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

Echtzeit-Datenbank

Wie oben beschrieben umfassen Echtzeit-Datenbankregeln drei grundlegende Elemente: den Datenbankspeicherort als Spiegel der JSON-Struktur der Datenbank, den Anforderungstyp und die Bedingung, die den Zugriff gewährt.

Datenbankspeicherort Database

Die Struktur Ihrer Regeln sollte der Struktur der Daten entsprechen, die Sie in Ihrer Datenbank gespeichert haben. In einer Chat-App mit einer Liste von Nachrichten können Sie beispielsweise Daten haben, die wie folgt aussehen:

  {
    "messages": {
      "message0": {
        "content": "Hello",
        "timestamp": 1405704370369
      },
      "message1": {
        "content": "Goodbye",
        "timestamp": 1405704395231
      },
      ...
    }
  }

Ihre Regeln sollten diese Struktur widerspiegeln. Beispielsweise:

  {
    "rules": {
      "messages": {
        "$message": {
          // only messages from the last ten minutes can be read
          ".read": "data.child('timestamp').val() > (now - 600000)",

          // new messages must have a string content and a number timestamp
          ".validate": "newData.hasChildren(['content', 'timestamp']) &&
                        newData.child('content').isString() &&
                        newData.child('timestamp').isNumber()"
        }
      }
    }
  }

Wie das obige Beispiel zeigt, unterstützen Echtzeit-Datenbankregeln eine $location Variable, um Pfadsegmenten abzugleichen. Verwenden Sie das Präfix $ vor Ihrem Pfadsegment, um Ihre Regel allen untergeordneten Knoten entlang des Pfads zuzuordnen.

  {
    "rules": {
      "rooms": {
        // This rule applies to any child of /rooms/, the key for each room id
        // is stored inside $room_id variable for reference
        "$room_id": {
          "topic": {
            // The room's topic can be changed if the room id has "public" in it
            ".write": "$room_id.contains('public')"
          }
        }
      }
    }
  }

Sie können die $variable parallel zu konstanten Pfadnamen verwenden.

  {
    "rules": {
      "widget": {
        // a widget can have a title or color attribute
        "title": { ".validate": true },
        "color": { ".validate": true },

        // but no other child paths are allowed
        // in this case, $other means any key excluding "title" and "color"
        "$other": { ".validate": false }
      }
    }
  }

Methode

In der Echtzeitdatenbank gibt es drei Arten von Regeln. Zwei dieser Regeltypen – read und write – gelten für die Methode einer eingehenden Anfrage. Der validate erzwingt Datenstrukturen und validiert das Format und den Inhalt von Daten. Regeln führen .validate Regeln aus, nachdem überprüft wurde, dass eine .write Regel Zugriff gewährt.

Regeltypen
.lesen Beschreibt, ob und wann Daten von Benutzern gelesen werden dürfen.
.schreiben Beschreibt, ob und wann Daten geschrieben werden dürfen.
.bestätigen Definiert, wie ein korrekt formatierter Wert aussieht, ob er untergeordnete Attribute hat und den Datentyp.

Wenn es keine Regel gibt, die dies zulässt, wird der Zugriff auf einen Pfad standardmäßig verweigert.

Baubedingungen

Cloud Firestore

Eine Bedingung ist ein boolescher Ausdruck, der bestimmt, ob eine bestimmte Operation zugelassen oder abgelehnt werden soll. Die request und resource stellen den Kontext für diese Bedingungen bereit.

Die request variable

Die request Variable umfasst folgende Felder und entsprechende Informationen:

request.auth

Ein JSON Web Token (JWT), das Authentifizierungsdaten von Firebase Authentication enthält. auth - Token enthält eine Reihe von Standard - Ansprüche und alle benutzerdefinierten Ansprüche Sie durch Firebase - Authentifizierung erstellen. Erfahren Sie mehr über Firebase-Sicherheitsregeln und -Authentifizierung .

request.method

Die request.method kann eine der Standardmethoden oder eine benutzerdefinierte Methode sein. Zur Vereinfachung der Schreibregeln, die für alle schreibgeschützten bzw. alle schreibgeschützten Standardmethoden gelten, gibt es auch die Komfortmethoden read und write .

request.params

Die request.params enthalten alle Daten, die sich nicht speziell auf die request.resource beziehen und für die Auswertung nützlich sein könnten. In der Praxis sollte diese Zuordnung für alle Standardmethoden leer sein und für benutzerdefinierte Methoden Nicht-Ressourcendaten enthalten. Dienste müssen darauf achten, den Typ von Schlüsseln und Werten, die als Parameter dargestellt werden, nicht umzubenennen oder zu ändern.

request.path

Der request.path ist der Pfad für die resource . Der Pfad ist relativ zum Dienst. Pfadsegmente, die nicht URL-sichere Zeichen wie / sind URL-codiert.

Die resource

Die resource ist der aktuelle Wert innerhalb des Dienstes, der als Zuordnung von Schlüssel-Wert-Paaren dargestellt wird. Das Verweisen auf eine resource innerhalb einer Bedingung führt zu höchstens einem Lesen des Werts aus dem Dienst. Diese Suche wird auf alle dienstbezogenen Kontingente für die Ressource angerechnet. Bei get Anfragen wird die resource nur bei Ablehnung auf das Kontingent angerechnet.

Operatoren und Operator-Priorität

Verwenden Sie die folgende Tabelle als Referenz für Operatoren und deren entsprechende Rangfolge in den Regeln für Cloud Firestore und Cloud Storage.

Gegeben beliebige Ausdrücke a und b , ein Feld f und ein Index i .

Operator Beschreibung Assoziativität
a[i] a() af Index, Aufruf, Feldzugriff links nach rechts
!a -a Unäre Negation rechts nach links
a/ba%ba*b Multiplikative Operatoren links nach rechts
a+b ab Additive Operatoren links nach rechts
a>ba>=ba Relationale Operatoren links nach rechts
a in b Existenz in Liste oder Karte links nach rechts
a is type Typvergleich, wobei type Bool, Int, Float, Zahl, String, Liste, Karte, Zeitstempel, Dauer, Pfad oder Latlng sein kann links nach rechts
a==ba!=b Vergleichsoperatoren links nach rechts
a && b Bedingtes UND links nach rechts
a || b Bedingtes ODER links nach rechts
a ? true_value : false_value Ternärer Ausdruck links nach rechts

Cloud-Speicher

Eine Bedingung ist ein boolescher Ausdruck, der bestimmt, ob eine bestimmte Operation zugelassen oder abgelehnt werden soll. Die request und resource stellen den Kontext für diese Bedingungen bereit.

Die request variable

Die request Variable umfasst folgende Felder und entsprechende Informationen:

request.auth

Ein JSON Web Token (JWT), das Authentifizierungsdaten von Firebase Authentication enthält. auth - Token enthält eine Reihe von Standard - Ansprüche und alle benutzerdefinierten Ansprüche Sie durch Firebase - Authentifizierung erstellen. Erfahren Sie mehr über Firebase-Sicherheitsregeln und -Authentifizierung .

request.method

Die request.method kann eine der Standardmethoden oder eine benutzerdefinierte Methode sein. Zur Vereinfachung der Schreibregeln, die für alle schreibgeschützten bzw. alle schreibgeschützten Standardmethoden gelten, gibt es auch die Komfortmethoden read und write .

request.params

Die request.params enthalten alle Daten, die sich nicht speziell auf die request.resource beziehen und für die Auswertung nützlich sein könnten. In der Praxis sollte diese Zuordnung für alle Standardmethoden leer sein und für benutzerdefinierte Methoden Nicht-Ressourcendaten enthalten. Dienste müssen darauf achten, den Typ von Schlüsseln und Werten, die als Parameter dargestellt werden, nicht umzubenennen oder zu ändern.

request.path

Der request.path ist der Pfad für die resource . Der Pfad ist relativ zum Dienst. Pfadsegmente, die nicht URL-sichere Zeichen wie / sind URL-codiert.

Die resource

Die resource ist der aktuelle Wert innerhalb des Dienstes, der als Zuordnung von Schlüssel-Wert-Paaren dargestellt wird. Das Verweisen auf eine resource innerhalb einer Bedingung führt zu höchstens einem Lesen des Werts aus dem Dienst. Diese Suche wird auf alle dienstbezogenen Kontingente für die Ressource angerechnet. Bei get Anfragen wird die resource nur bei Ablehnung auf das Kontingent angerechnet.

Operatoren und Operator-Priorität

Verwenden Sie die folgende Tabelle als Referenz für Operatoren und deren entsprechende Rangfolge in den Regeln für Cloud Firestore und Cloud Storage.

Gegeben beliebige Ausdrücke a und b , ein Feld f und ein Index i .

Operator Beschreibung Assoziativität
a[i] a() af Index, Aufruf, Feldzugriff links nach rechts
!a -a Unäre Negation rechts nach links
a/ba%ba*b Multiplikative Operatoren links nach rechts
a+b ab Additive Operatoren links nach rechts
a>ba>=ba Relationale Operatoren links nach rechts
a in b Existenz in Liste oder Karte links nach rechts
a is type Typvergleich, wobei type Bool, Int, Float, Zahl, String, Liste, Karte, Zeitstempel, Dauer, Pfad oder Latlng sein kann links nach rechts
a==ba!=b Vergleichsoperatoren links nach rechts
a && b Bedingtes UND links nach rechts
a || b Bedingtes ODER links nach rechts
a ? true_value : false_value Ternärer Ausdruck links nach rechts

Echtzeit-Datenbank

Eine Bedingung ist ein boolescher Ausdruck, der bestimmt, ob eine bestimmte Operation zugelassen oder abgelehnt werden soll. Sie können diese Bedingungen in Echtzeit-Datenbankregeln wie folgt definieren.

Vordefinierte Variablen

Es gibt eine Reihe hilfreicher vordefinierter Variablen, auf die innerhalb einer Regeldefinition zugegriffen werden kann. Hier ist jeweils eine kurze Zusammenfassung:

Vordefinierte Variablen
jetzt Die aktuelle Zeit in Millisekunden seit der Linux-Epoche. Dies funktioniert besonders gut für die Validierung von Zeitstempeln, die mit firebase.database.ServerValue.TIMESTAMP des SDK erstellt wurden.
Wurzel Ein RuleDataSnapshot, der den Stammpfad in der Firebase-Datenbank darstellt, wie er vor dem versuchten Vorgang vorhanden war.
neue Daten Ein RuleDataSnapshot, der die Daten darstellt, wie sie nach dem versuchten Vorgang vorhanden wären. Es enthält die neu geschriebenen Daten und die vorhandenen Daten.
Daten Ein RuleDataSnapshot, der die Daten darstellt, wie sie vor dem versuchten Vorgang vorhanden waren.
$-Variablen Ein Platzhalterpfad, der verwendet wird, um IDs und dynamische untergeordnete Schlüssel darzustellen.
auth Stellt die Tokennutzlast eines authentifizierten Benutzers dar.

Diese Variablen können überall in Ihren Regeln verwendet werden. Die folgenden Sicherheitsregeln stellen beispielsweise sicher, dass die in den /foo/ -Knoten geschriebenen Daten eine Zeichenfolge mit weniger als 100 Zeichen sein müssen:

{
  "rules": {
    "foo": {
      // /foo is readable by the world
      ".read": true,

      // /foo is writable by the world
      ".write": true,

      // data written to /foo must be a string less than 100 characters
      ".validate": "newData.isString() && newData.val().length < 100"
    }
  }
}

Datenbasierte Regeln

Alle Daten in Ihrer Datenbank können in Ihren Regeln verwendet werden. Mit den vordefinierten Variablen root , data und newData können Sie auf jeden Pfad zugreifen, wie er vor oder nach einem Schreibereignis vorhanden wäre.

Betrachten Sie dieses Beispiel, das Schreiboperationen zulässt, solange der Wert des /allow_writes/ true , der übergeordnete Knoten kein readOnly Flag gesetzt hat und in den neu geschriebenen Daten ein Kind namens foo vorhanden ist:

".write": "root.child('allow_writes').val() === true &&
          !data.parent().child('readOnly').exists() &&
          newData.child('foo').exists()"

Abfragebasierte Regeln

Obwohl Sie Regeln nicht als Filter verwenden können, können Sie den Zugriff auf Teilmengen von Daten einschränken, indem Sie Abfrageparameter in Ihren Regeln verwenden. query. Ausdrücke in Ihren Regeln, um Lese- oder Schreibzugriff basierend auf Abfrageparametern zu gewähren.

Die folgende abfragebasierte Regel verwendet beispielsweise benutzerbasierte Sicherheitsregeln und abfragebasierte Regeln, um den Zugriff auf Daten in der baskets Sammlung auf die Warenkörbe zu beschränken, die der aktive Benutzer besitzt:

"baskets": {
  ".read": "auth.uid != null &&
            query.orderByChild == 'owner' &&
            query.equalTo == auth.uid" // restrict basket access to owner of basket
}

Die folgende Abfrage, die die Abfrageparameter in der Regel enthält, wäre erfolgreich:

db.ref("baskets").orderByChild("owner")
                 .equalTo(auth.currentUser.uid)
                 .on("value", cb)                 // Would succeed

Abfragen, die die Parameter in der Regel nicht enthalten, schlagen jedoch mit einem PermissionDenied Fehler fehl:

db.ref("baskets").on("value", cb)                 // Would fail with PermissionDenied

Sie können auch abfragebasierte Regeln verwenden, um zu begrenzen, wie viele Daten ein Client durch Lesevorgänge herunterlädt.

Die folgende Regel beschränkt beispielsweise den Lesezugriff auf die ersten 1000 Ergebnisse einer Abfrage, sortiert nach Priorität:

messages: {
  ".read": "query.orderByKey &&
            query.limitToFirst <= 1000"
}

// Example queries:

db.ref("messages").on("value", cb)                // Would fail with PermissionDenied

db.ref("messages").limitToFirst(1000)
                  .on("value", cb)                // Would succeed (default order by key)

Die folgende query. Ausdrücke sind in Echtzeit-Datenbankregeln verfügbar.

Abfragebasierte Regelausdrücke
Ausdruck Art Beschreibung
query.orderByKey
query.orderByPriority
query.orderByValue
boolesch True für Abfragen, die nach Schlüssel, Priorität oder Wert geordnet sind. Sonst falsch.
query.orderByChild Schnur
Null
Verwenden Sie eine Zeichenfolge, um den relativen Pfad zu einem untergeordneten Knoten darzustellen. Beispiel: query.orderByChild == "address/zip" . Wenn die Abfrage nicht nach einem untergeordneten Knoten sortiert ist, ist dieser Wert null.
query.startAt
query.endAt
query.equalTo
Schnur
Nummer
boolesch
Null
Ruft die Grenzen der ausgeführten Abfrage ab oder gibt null zurück, wenn kein gebundener Satz vorhanden ist.
query.limitToFirst
query.limitToLast
Nummer
Null
Ruft das Limit für die ausgeführte Abfrage ab oder gibt null zurück, wenn kein Limit festgelegt ist.

Betreiber

Echtzeit-Datenbankregeln unterstützen eine Reihe von Operatoren, mit denen Sie Variablen in der Bedingungsanweisung kombinieren können. Die vollständige Liste der Operatoren finden Sie in der Referenzdokumentation .

Bedingungen schaffen

Ihre tatsächlichen Bedingungen variieren je nach dem Zugriff, den Sie gewähren möchten. Regeln bieten absichtlich ein enormes Maß an Flexibilität, sodass die Regeln Ihrer App letztendlich so einfach oder komplex sein können, wie Sie es benötigen.

Eine Anleitung zum Erstellen einfacher, produktionsbereiter Regeln finden Sie unter Grundlegende Sicherheitsregeln .