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 Firestore- und Cloud Storage-Regeln verwenden eine Sprache, die auf der Common Expression Language (CEL) basiert und auf CEL mit match
und allow
Anweisungen aufbaut, die bedingt gewährten Zugriff unterstützen.
Da es sich jedoch um benutzerdefinierte Sprachen handelt, ist eine Lernkurve erforderlich. 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>>
}
}
Beim Erstellen der Regeln ist es wichtig, die folgenden Schlüsselkonzepte zu verstehen:
- Anfrage: Die Methode oder Methoden, die in der
allow
Anweisung aufgerufen werden. Dies sind Methoden, deren Ausführung Sie zulassen. Die Standardmethoden sind:get
,list
,create
,update
unddelete
. Die komfortablenread
undwrite
ermöglichen einen umfassenden 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 Anfrage zulässt, wenn sie als wahr ausgewertet wird.
Jedes dieser Konzepte wird im Folgenden 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>>
}
}
Beim Erstellen der Regeln ist es wichtig, die folgenden Schlüsselkonzepte zu verstehen:
- Anfrage: Die Methode oder Methoden, die in der
allow
Anweisung aufgerufen werden. Dies sind Methoden, deren Ausführung Sie zulassen. Die Standardmethoden sind:get
,list
,create
,update
unddelete
. Die komfortablenread
undwrite
ermöglichen einen umfassenden 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 Anfrage zulässt, wenn sie als wahr ausgewertet wird.
Jedes dieser Konzepte wird im Folgenden ausführlicher beschrieben.
Echtzeitdatenbank
In der Echtzeitdatenbank 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>>
}
}
}
Die Regel besteht aus drei Grundelementen:
- Pfad: Der Datenbankspeicherort. Dies spiegelt die JSON-Struktur Ihrer Datenbank wider.
- Anfrage: Dies sind die Methoden, die die Regel verwendet, um Zugriff zu gewähren. Die
read
undwrite
gewähren umfassenden Lese- und Schreibzugriff, währendvalidate
als sekundäre Überprüfung fungieren, um den Zugriff auf der Grundlage eingehender oder vorhandener Daten zu gewähren. - Bedingung: Die Bedingung, die eine Anfrage zulässt, wenn sie als wahr ausgewertet wird.
Regelkonstrukte
Cloud Firestore
Die Grundelemente einer Regel in Cloud Firestore und Cloud Storage sind 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 Speicher-Bucket, für den die Regeln gelten. - Die
allow
Anweisung: Stellt Bedingungen für die Gewährung des Zugriffs bereit, differenziert nach Methoden. Zu den unterstützten Methoden gehören:get
,list
,create
,update
,delete
sowie die praktischen Methodenread
undwrite
. - Optionale
function
: Bieten die Möglichkeit, Bedingungen für die Verwendung in mehreren Regeln zu kombinieren und zu umschließen.
Der service
enthält einen oder mehrere match
Blöcke 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 Firebase Security Rules-Sprache unterstützt auch function
.
Syntaxversion
Die syntax
gibt die Version der Firebase Rules-Sprache an, die zum Schreiben der Quelle verwendet wird. Die neueste Version der Sprache ist v2
.
rules_version = '2';
service cloud.firestore {
...
}
Wenn keine rules_version
Anweisung angegeben wird, werden Ihre Regeln mithilfe der v1
Engine ausgewertet.
Service
Die service
definiert, für welches Firebase-Produkt oder welchen Firebase-Dienst Ihre Regeln gelten. Sie können nur eine service
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 mithilfe der Firebase-CLI Regeln für Cloud Firestore und Cloud Storage definieren, müssen Sie diese in separaten Dateien verwalten.
Übereinstimmen
Ein match
Block deklariert ein path
, das mit dem Pfad für die angeforderte Operation (dem eingehenden request.path
) abgeglichen wird. Der Hauptteil der match
muss einen oder mehrere verschachtelte match
, allow
oder function
enthalten. Der Pfad in verschachtelten match
Blöcken ist relativ zum Pfad im übergeordneten match
Block.
Das path
ist ein verzeichnisähnlicher Name, der Variablen oder Platzhalter enthalten kann. Das path
ermöglicht Einzelpfad-Segment- und Mehrpfad-Segmentübereinstimmungen. Alle in einem path
gebundenen Variablen sind im match
oder in jedem verschachtelten Bereich sichtbar, in dem der path
deklariert ist.
Übereinstimmungen mit einem path
können teilweise oder vollständig sein:
- Teilweise Übereinstimmungen: Das
path
ist eine Präfixübereinstimmung mitrequest.path
. - Vollständige Übereinstimmungen: Das
path
stimmt mit dem gesamtenrequest.path
überein.
Bei einer vollständigen Übereinstimmung werden die Regeln innerhalb des Blocks ausgewertet. Bei einer teilweisen Übereinstimmung werden die verschachtelten match
getestet, um festzustellen, ob ein verschachtelter path
die Übereinstimmung abschließt .
Die Regeln in jeder vollständigen match
werden ausgewertet, um zu bestimmen, ob die Anforderung zugelassen wird. Wenn eine übereinstimmende Regel Zugriff gewährt, ist die Anfrage zulässig. Wenn keine passende 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, unterstützen die path
die folgenden Variablen:
- Einzelsegment-Platzhalter: Eine Platzhaltervariable wird in einem Pfad deklariert, indem eine Variable in geschweifte Klammern eingeschlossen wird:
{variable}
. Auf diese Variable kann innerhalb dermatch
Anweisung alsstring
zugegriffen werden. - Rekursiver Platzhalter: Der rekursive oder Multisegment-Platzhalter entspricht mehreren Pfadsegmenten auf 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 dermatch
Anweisung alspath
zugegriffen werden.
Erlauben
Der match
Block enthält eine oder mehrere allow
Anweisungen. Das sind Ihre eigentlichen Regeln. Sie können allow
auf eine oder mehrere Methoden anwenden. Die Bedingungen einer allow
müssen als „wahr“ ausgewertet werden, damit Cloud Firestore oder Cloud Storage eingehende Anfragen gewähren kann. Sie können allow
Anweisungen auch ohne Bedingungen schreiben, beispielsweise allow read
. Wenn die allow
Anweisung jedoch keine Bedingung enthält, lässt sie die Anforderung für diese Methode immer zu.
Wenn eine der allow
für die Methode erfüllt ist, wird die Anforderung zugelassen. Wenn darüber hinaus eine umfassendere Regel den Zugriff gewährt, gewähren die Regeln den Zugriff und ignorieren alle detaillierteren Regeln, die den Zugriff einschränken könnten.
Betrachten Sie das folgende Beispiel, in dem jeder Benutzer jede seiner eigenen Dateien lesen oder löschen kann. Eine detailliertere Regel erlaubt Schreibvorgänge nur, wenn der Benutzer, der den Schreibvorgang anfordert, Eigentümer der Datei ist und es sich bei der Datei um eine PNG-Datei handelt. Ein Benutzer kann alle Dateien im Unterpfad löschen – auch wenn es sich nicht um PNGs handelt –, da 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 eingehenden Anforderungen derselben Methode Zugriff gewährt.
Methode | Art der Anfrage |
---|---|
Convenience-Methoden | |
read | Jede Art von Leseanfrage |
write | Jede Art von Schreibanfrage |
Standardmethoden | |
get | Leseanfragen für einzelne Dokumente oder Dateien |
list | Lesen Sie Anfragen für Anfragen und Inkasso |
create | Schreiben Sie neue Dokumente oder Dateien |
update | Schreiben Sie in vorhandene Datenbankdokumente oder aktualisieren Sie Dateimetadaten |
delete | Daten löschen |
Sie können keine Lesemethoden im selben match
Block oder widersprüchliche Schreibmethoden in derselben path
überlappen.
Beispielsweise würden die folgenden Regeln 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 einbinden, die Sie in Ihrem Regelsatz wiederverwenden können. Sicherheitsregeln unterstützen benutzerdefinierte Funktionen. Die Syntax für benutzerdefinierte Funktionen ähnelt ein wenig der von JavaScript, Sicherheitsregelfunktionen sind jedoch in einer domänenspezifischen Sprache geschrieben, die einige wichtige Einschränkungen aufweist:
- Funktionen können nur eine einzige
return
Anweisung enthalten. Sie dürfen 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 dieresource
und integrierte Funktionen wieget()
undexists()
. - Funktionen können andere Funktionen aufrufen, dürfen jedoch nicht rekursiv sein. Die Gesamttiefe des Aufrufstapels ist auf 20 begrenzt.
- In der Regelversion
v2
können Funktionen Variablen mithilfe des Schlüsselwortslet
definieren. Funktionen können bis zu 10 Let-Bindungen haben, müssen jedoch mit einer Return-Anweisung enden.
Eine Funktion wird mit dem Schlüsselwort function
definiert und akzeptiert null oder mehr Argumente. Beispielsweise möchten Sie möglicherweise die beiden in den obigen Beispielen verwendeten Arten von Bedingungen 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 Semikolons 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 eine Suche in der Admins-Sammlung erzwingt. Für eine verzögerte Auswertung ohne unnötige Suchvorgänge nutzen Sie die Kurzschlussfunktion von &&
(AND) und ||
(OR)-Vergleiche, um eine zweite Funktion nur dann aufzurufen, wenn isAuthor
als wahr (für &&
Vergleiche) oder falsch (für ||
-Vergleiche) angezeigt 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 bei zunehmender Komplexität Ihrer Regeln besser wartbar.
Cloud-Speicher
Die Grundelemente einer Regel in Cloud Firestore und Cloud Storage sind 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 Speicher-Bucket, für den die Regeln gelten. - Die
allow
Anweisung: Stellt Bedingungen für die Gewährung des Zugriffs bereit, differenziert nach Methoden. Zu den unterstützten Methoden gehören:get
,list
,create
,update
,delete
sowie die praktischen Methodenread
undwrite
. - Optionale
function
: Bieten die Möglichkeit, Bedingungen für die Verwendung in mehreren Regeln zu kombinieren und zu umschließen.
Der service
enthält einen oder mehrere match
Blöcke 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 Firebase Security Rules-Sprache unterstützt auch function
.
Syntaxversion
Die syntax
gibt die Version der Firebase-Regelsprache an, die zum Schreiben der Quelle verwendet wurde. Die neueste Version der Sprache ist v2
.
rules_version = '2';
service cloud.firestore {
...
}
Wenn keine rules_version
Anweisung angegeben wird, werden Ihre Regeln mithilfe der v1
Engine ausgewertet.
Service
Die service
definiert, für welches Firebase-Produkt oder welchen Firebase-Dienst Ihre Regeln gelten. Sie können nur eine service
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 mithilfe der Firebase-CLI Regeln für Cloud Firestore und Cloud Storage definieren, müssen Sie diese in separaten Dateien verwalten.
Übereinstimmen
Ein match
Block deklariert ein path
, das mit dem Pfad für die angeforderte Operation (dem eingehenden request.path
) abgeglichen wird. Der Hauptteil der match
muss einen oder mehrere verschachtelte match
, allow
oder function
enthalten. Der Pfad in verschachtelten match
Blöcken ist relativ zum Pfad im übergeordneten match
Block.
Das path
ist ein verzeichnisähnlicher Name, der Variablen oder Platzhalter enthalten kann. Das path
ermöglicht Einzelpfad-Segment- und Mehrpfad-Segmentübereinstimmungen. Alle in einem path
gebundenen Variablen sind im match
oder in jedem verschachtelten Bereich sichtbar, in dem der path
deklariert ist.
Übereinstimmungen mit einem path
können teilweise oder vollständig sein:
- Teilweise Übereinstimmungen: Das
path
ist eine Präfixübereinstimmung mitrequest.path
. - Vollständige Übereinstimmungen: Das
path
stimmt mit dem gesamtenrequest.path
überein.
Bei einer vollständigen Übereinstimmung werden die Regeln innerhalb des Blocks ausgewertet. Bei einer teilweisen Übereinstimmung werden die verschachtelten match
getestet, um festzustellen, ob ein verschachtelter path
die Übereinstimmung abschließt .
Die Regeln in jeder vollständigen match
werden ausgewertet, um zu bestimmen, ob die Anforderung zugelassen wird. Wenn eine übereinstimmende Regel Zugriff gewährt, ist die Anfrage zulässig. Wenn keine passende 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, unterstützen die path
die folgenden Variablen:
- Einzelsegment-Platzhalter: Eine Platzhaltervariable wird in einem Pfad deklariert, indem eine Variable in geschweifte Klammern eingeschlossen wird:
{variable}
. Auf diese Variable kann innerhalb dermatch
Anweisung alsstring
zugegriffen werden. - Rekursiver Platzhalter: Der rekursive oder Multisegment-Platzhalter entspricht mehreren Pfadsegmenten auf 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 dermatch
Anweisung alspath
zugegriffen werden.
Erlauben
Der match
Block enthält eine oder mehrere allow
Anweisungen. Das sind Ihre eigentlichen Regeln. Sie können allow
auf eine oder mehrere Methoden anwenden. Die Bedingungen einer allow
müssen als „wahr“ ausgewertet werden, damit Cloud Firestore oder Cloud Storage eingehende Anfragen gewähren kann. Sie können allow
Anweisungen auch ohne Bedingungen schreiben, beispielsweise allow read
. Wenn die allow
Anweisung jedoch keine Bedingung enthält, lässt sie die Anforderung für diese Methode immer zu.
Wenn eine der allow
für die Methode erfüllt ist, wird die Anforderung zugelassen. Wenn darüber hinaus eine umfassendere Regel den Zugriff gewährt, gewähren die Regeln den Zugriff und ignorieren alle detaillierteren Regeln, die den Zugriff einschränken könnten.
Betrachten Sie das folgende Beispiel, in dem jeder Benutzer jede seiner eigenen Dateien lesen oder löschen kann. Eine detailliertere Regel erlaubt Schreibvorgänge nur, wenn der Benutzer, der den Schreibvorgang anfordert, Eigentümer der Datei ist und es sich bei der Datei um eine PNG-Datei handelt. Ein Benutzer kann alle Dateien im Unterpfad löschen – auch wenn es sich nicht um PNGs handelt –, da 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 eingehenden Anforderungen derselben Methode Zugriff gewährt.
Methode | Art der Anfrage |
---|---|
Convenience-Methoden | |
read | Jede Art von Leseanfrage |
write | Jede Art von Schreibanfrage |
Standardmethoden | |
get | Leseanfragen für einzelne Dokumente oder Dateien |
list | Lesen Sie Anfragen für Anfragen und Inkasso |
create | Schreiben Sie neue Dokumente oder Dateien |
update | Schreiben Sie in vorhandene Datenbankdokumente oder aktualisieren Sie Dateimetadaten |
delete | Daten löschen |
Sie können keine Lesemethoden im selben match
Block oder widersprüchliche Schreibmethoden in derselben path
überlappen.
Beispielsweise würden die folgenden Regeln 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 einbinden, die Sie in Ihrem Regelsatz wiederverwenden können. Sicherheitsregeln unterstützen benutzerdefinierte Funktionen. Die Syntax für benutzerdefinierte Funktionen ähnelt ein wenig der von JavaScript, Sicherheitsregelfunktionen sind jedoch in einer domänenspezifischen Sprache geschrieben, die einige wichtige Einschränkungen aufweist:
- Funktionen können nur eine einzige
return
Anweisung enthalten. Sie dürfen 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 dieresource
und integrierte Funktionen wieget()
undexists()
. - Funktionen können andere Funktionen aufrufen, dürfen jedoch nicht rekursiv sein. Die Gesamttiefe des Aufrufstapels ist auf 20 begrenzt.
- In der Regelversion
v2
können Funktionen Variablen mithilfe des Schlüsselwortslet
definieren. Funktionen können bis zu 10 Let-Bindungen haben, müssen jedoch mit einer Return-Anweisung enden.
Eine Funktion wird mit dem Schlüsselwort function
definiert und akzeptiert null oder mehr Argumente. Beispielsweise möchten Sie möglicherweise die beiden in den obigen Beispielen verwendeten Arten von Bedingungen 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 Semikolons 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 eine Suche in der Admins-Sammlung erzwingt. Für eine verzögerte Auswertung ohne unnötige Suchvorgänge nutzen Sie die Kurzschlussfunktion von &&
(AND) und ||
(OR)-Vergleiche, um eine zweite Funktion nur aufzurufen, wenn isAuthor
als wahr (für &&
Vergleiche) oder falsch (für ||
-Vergleiche) angezeigt 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 bei zunehmender Komplexität Ihrer Regeln besser wartbar.
Echtzeitdatenbank
Wie oben beschrieben umfassen Echtzeitdatenbankregeln drei Grundelemente: den Datenbankspeicherort als Spiegel der JSON-Struktur der Datenbank, den Anforderungstyp und die Bedingung, die den Zugriff gewährt.
Datenbankspeicherort
Die Struktur Ihrer Regeln sollte der Struktur der Daten folgen, die Sie in Ihrer Datenbank gespeichert haben. In einer Chat-App mit einer Liste von Nachrichten könnten beispielsweise Daten vorliegen, die wie folgt aussehen:
{
"messages": {
"message0": {
"content": "Hello",
"timestamp": 1405704370369
},
"message1": {
"content": "Goodbye",
"timestamp": 1405704395231
},
...
}
}
Ihre Regeln sollten diese Struktur widerspiegeln. Zum Beispiel:
{
"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 Echtzeitdatenbankregeln eine $location
-Variable, um Pfadsegmente abzugleichen. Verwenden Sie das Präfix $
vor Ihrem Pfadsegment, um Ihre Regel an alle untergeordneten Knoten entlang des Pfads anzupassen.
{
"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
auch 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 der Daten. Regeln führen .validate
Regeln aus, nachdem sie überprüft haben, ob 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 über untergeordnete Attribute verfügt und welchen Datentyp er hat. |
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 ein bestimmter Vorgang zugelassen oder verweigert werden soll. Die request
und resource
stellen den Kontext für diese Bedingungen bereit.
Die request
Die request
umfasst die folgenden Felder und entsprechende Informationen:
request.auth
Ein JSON-Web-Token (JWT), das Authentifizierungsdaten von Firebase Authentication enthält. Das auth
enthält eine Reihe von Standardansprüchen und alle benutzerdefinierten Ansprüche, die Sie über die Firebase-Authentifizierung erstellen. Erfahren Sie mehr über Firebase-Sicherheitsregeln und -Authentifizierung .
request.method
Bei der request.method
kann es sich um eine beliebige Standardmethode oder eine benutzerdefinierte Methode handeln. Zur Vereinfachung des Schreibens gibt es auch die Komfortmethoden read
und write
, die für alle schreibgeschützten bzw. alle schreibgeschützten Standardmethoden gelten.
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 Karte für alle Standardmethoden leer sein und für benutzerdefinierte Methoden Nicht-Ressourcendaten enthalten. Dienste müssen darauf achten, die als Parameter dargestellten Schlüssel und Werte nicht umzubenennen oder deren Typ 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 /
enthalten, sind URL-codiert.
Die resource
Die resource
ist der aktuelle Wert innerhalb des Dienstes, der als Karte von Schlüssel-Wert-Paaren dargestellt wird. Das Verweisen auf eine resource
innerhalb einer Bedingung führt dazu, dass der Wert höchstens einmal vom Dienst gelesen wird. 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 Operatorpriorität
Verwenden Sie die folgende Tabelle als Referenz für Operatoren und ihre entsprechende Rangfolge in Regeln für Cloud Firestore und Cloud Storage.
Gegeben seien 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 | Vergleichsoperatoren | 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 Breite 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 ein bestimmter Vorgang zugelassen oder verweigert werden soll. Die request
und resource
stellen den Kontext für diese Bedingungen bereit.
Die request
Die request
umfasst die folgenden Felder und entsprechende Informationen:
request.auth
Ein JSON-Web-Token (JWT), das Authentifizierungsdaten von Firebase Authentication enthält. Das auth
enthält eine Reihe von Standardansprüchen und alle benutzerdefinierten Ansprüche, die Sie über die Firebase-Authentifizierung erstellen. Erfahren Sie mehr über Firebase-Sicherheitsregeln und -Authentifizierung .
request.method
Bei der request.method
kann es sich um eine beliebige Standardmethode oder eine benutzerdefinierte Methode handeln. Zur Vereinfachung des Schreibens gibt es auch die Komfortmethoden read
und write
, die für alle schreibgeschützten bzw. alle schreibgeschützten Standardmethoden gelten.
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 Karte für alle Standardmethoden leer sein und für benutzerdefinierte Methoden Nicht-Ressourcendaten enthalten. Dienste müssen darauf achten, die als Parameter dargestellten Schlüssel und Werte nicht umzubenennen oder deren Typ 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 /
enthalten, sind URL-codiert.
Die resource
Die resource
ist der aktuelle Wert innerhalb des Dienstes, der als Karte von Schlüssel-Wert-Paaren dargestellt wird. Das Verweisen auf eine resource
innerhalb einer Bedingung führt dazu, dass der Wert höchstens einmal vom Dienst gelesen wird. 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 Operatorpriorität
Verwenden Sie die folgende Tabelle als Referenz für Operatoren und ihre entsprechende Rangfolge in Regeln für Cloud Firestore und Cloud Storage.
Gegeben seien 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 | Vergleichsoperatoren | 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 Breite 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 |
Echtzeitdatenbank
Eine Bedingung ist ein boolescher Ausdruck, der bestimmt, ob ein bestimmter Vorgang zugelassen oder verweigert werden soll. Sie können diese Bedingungen in Realtime Database Rules auf folgende Weise 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 eignet sich 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 umfasst die neuen Daten, die geschrieben werden, und die vorhandenen Daten. |
Daten | Ein RuleDataSnapshot, der die Daten darstellt, wie sie vor dem versuchten Vorgang vorhanden waren. |
$-Variablen | Ein Platzhalterpfad zur Darstellung von IDs und dynamischen untergeordneten Schlüsseln. |
Autor | Stellt die Token-Nutzlast eines authentifizierten Benutzers dar. |
Diese Variablen können überall in Ihren Regeln verwendet werden. Die folgenden Sicherheitsregeln stellen beispielsweise sicher, dass die auf 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. Mithilfe der 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 Schreibvorgänge zulässt, solange der Wert des Knotens /allow_writes/
true
ist, für den übergeordneten Knoten kein readOnly
Flag gesetzt ist und in den neu geschriebenen Daten ein untergeordneter Knoten 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 beschrä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
nur auf die Einkaufskörbe zu beschränken, deren Eigentümer der aktive Benutzer ist:
"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
Allerdings würden Abfragen, die die Parameter in der Regel nicht enthalten, mit einem PermissionDenied
Fehler fehlschlagen:
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 nur auf die ersten 1000 Ergebnisse einer Abfrage, geordnet 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-Datenbanksicherheitsregeln verfügbar.
Abfragebasierte Regelausdrücke | ||
---|---|---|
Ausdruck | Typ | Beschreibung |
query.orderByKey query.orderByPriority query.orderByValue | Boolescher Wert | True für Abfragen, die nach Schlüssel, Priorität oder Wert sortiert sind. Sonst falsch. |
query.orderByChild | Zeichenfolge 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 | Zeichenfolge Nummer Boolescher Wert Null | Ruft die Grenzen der ausführenden Abfrage ab oder gibt null zurück, wenn kein gebundener Satz vorhanden ist. |
query.limitToFirst query.limitToLast | Nummer Null | Ruft den Grenzwert für die ausgeführte Abfrage ab oder gibt null zurück, wenn kein Grenzwert festgelegt ist. |
Betreiber
Echtzeitdatenbankregeln 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 bewusst ein enormes Maß an Flexibilität, sodass die Regeln Ihrer App letztlich so einfach oder so komplex sein können, wie Sie es benötigen.
Hinweise zum Erstellen einfacher, produktionsbereiter Regeln finden Sie unter Grundlegende Sicherheitsregeln .