Verwenden Sie die Bedingungen in den Firebase Cloud Storage-Sicherheitsregeln

Dieser Leitfaden baut auf dem Erlernen der Kernsyntax des Sprachleitfadens „Firebase Security Rules“ auf und zeigt, wie Sie Bedingungen zu Ihren Firebase Security Rules für Cloud Storage hinzufügen.

Der Hauptbaustein der Cloud Storage-Sicherheitsregeln ist die Bedingung . Eine Bedingung ist ein boolescher Ausdruck, der bestimmt, ob ein bestimmter Vorgang zugelassen oder verweigert werden soll. Bei Grundregeln funktioniert die Verwendung true und false Literale als Bedingungen vollkommen gut. Aber die Firebase Security Rules for Cloud Storage-Sprache bietet Ihnen Möglichkeiten, komplexere Bedingungen zu schreiben, die Folgendes können:

  • Überprüfen Sie die Benutzerauthentifizierung
  • Eingehende Daten validieren

Authentifizierung

Firebase Security Rules für Cloud Storage lässt sich in Firebase Authentication integrieren, um eine leistungsstarke benutzerbasierte Authentifizierung für Cloud Storage bereitzustellen. Dies ermöglicht eine detaillierte Zugriffskontrolle basierend auf Ansprüchen eines Firebase-Authentifizierungstokens.

Wenn ein authentifizierter Benutzer eine Anfrage an Cloud Storage durchführt, wird die Variable request.auth mit der uid des Benutzers ( request.auth.uid ) sowie den Ansprüchen des Firebase Authentication JWT ( request.auth.token ) gefüllt.

Darüber hinaus werden bei Verwendung der benutzerdefinierten Authentifizierung zusätzliche Ansprüche im Feld request.auth.token angezeigt.

Wenn ein nicht authentifizierter Benutzer eine Anfrage ausführt, ist die Variable request.auth null .

Unter Verwendung dieser Daten gibt es mehrere gängige Möglichkeiten, die Authentifizierung zum Sichern von Dateien zu verwenden:

  • Öffentlich: request.auth ignorieren
  • Authentifiziert privat: Stellen Sie sicher, dass request.auth nicht null ist
  • Privater Benutzer: Überprüfen Sie, ob request.auth.uid einer Pfad- uid entspricht
  • Gruppe privat: Überprüfen Sie, ob die Ansprüche des benutzerdefinierten Tokens mit einem ausgewählten Anspruch übereinstimmen, oder lesen Sie die Dateimetadaten, um festzustellen, ob ein Metadatenfeld vorhanden ist

Öffentlich

Jede Regel, die den request.auth Kontext nicht berücksichtigt, kann als public Regel betrachtet werden, da sie den Authentifizierungskontext des Benutzers nicht berücksichtigt. Diese Regeln können nützlich sein, um öffentliche Daten wie Spielressourcen, Sounddateien oder andere statische Inhalte anzuzeigen.

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

Authentifizierter Privater

In bestimmten Fällen möchten Sie möglicherweise, dass Daten für alle authentifizierten Benutzer Ihrer Anwendung sichtbar sind, nicht jedoch für nicht authentifizierte Benutzer. Da die Variable request.auth für alle nicht authentifizierten Benutzer null ist, müssen Sie lediglich prüfen, ob die Variable „ request.auth vorhanden ist, um eine Authentifizierung anzufordern:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

Benutzer privat

Der mit Abstand häufigste Anwendungsfall für request.auth wird darin bestehen, einzelnen Benutzern detaillierte Berechtigungen für ihre Dateien zu gewähren: vom Hochladen von Profilbildern bis zum Lesen privater Dokumente.

Da Dateien in Cloud Storage über einen vollständigen „Pfad“ zur Datei verfügen, ist alles, was erforderlich ist, um eine von einem Benutzer kontrollierte Datei zu erstellen, eine eindeutige, benutzeridentifizierende Information im Dateinamen-Präfix (z. B. die uid des Benutzers), die überprüft werden kann wenn die Regel ausgewertet wird:

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth.uid == userId;
}

Gruppe privat

Ein weiterer ebenso häufiger Anwendungsfall besteht darin, Gruppenberechtigungen für ein Objekt zuzulassen, beispielsweise um mehreren Teammitgliedern die Zusammenarbeit an einem gemeinsamen Dokument zu ermöglichen. Hierfür gibt es mehrere Ansätze:

  • Erstellen Sie ein benutzerdefiniertes Firebase-Authentifizierungstoken, das zusätzliche Informationen zu einem Gruppenmitglied enthält (z. B. eine Gruppen-ID).
  • Fügen Sie Gruppeninformationen (z. B. eine Gruppen-ID oder eine Liste autorisierter uid ) in die Dateimetadaten ein

Sobald diese Daten im Token oder in den Dateimetadaten gespeichert sind, kann innerhalb einer Regel darauf verwiesen werden:

// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
  allow read: if resource.metadata.owner == request.auth.token.groupId;
  allow write: if request.auth.token.groupId == groupId;
}

Bewertung anfordern

Uploads, Downloads, Metadatenänderungen und Löschungen werden anhand der an Cloud Storage gesendeten request ausgewertet. Zusätzlich zur eindeutigen ID des Benutzers und der Firebase-Authentifizierungsnutzlast im Objekt request.auth , wie oben beschrieben, enthält die request den Dateipfad, in dem die Anforderung ausgeführt wird, die Zeit, zu der die Anforderung empfangen wird, und den neuen resource , wenn Die Anfrage ist ein Schreibvorgang.

Das request enthält außerdem die eindeutige ID des Benutzers und die Firebase-Authentifizierungsnutzlast im Objekt „ request.auth “, was im Abschnitt „Benutzerbasierte Sicherheit“ der Dokumentation näher erläutert wird.

Eine vollständige Liste der Eigenschaften im request finden Sie unten:

Eigentum Typ Beschreibung
auth map<string, string> Wenn ein Benutzer angemeldet ist, werden uid , die eindeutige ID des Benutzers, und token , eine Karte der Firebase Authentication JWT-Ansprüche, bereitgestellt. Andernfalls ist es null .
params map<string, string> Karte, die die Abfrageparameter der Anfrage enthält.
path Weg Ein path , der den Pfad darstellt, auf dem die Anforderung ausgeführt wird.
resource map<string, string> Der neue Ressourcenwert, der nur bei write vorhanden ist.
time Zeitstempel Ein Zeitstempel, der die Serverzeit angibt, zu der die Anfrage ausgewertet wird.

Ressourcenbewertung

Beim Auswerten von Regeln möchten Sie möglicherweise auch die Metadaten der Datei auswerten, die hochgeladen, heruntergeladen, geändert oder gelöscht wird. Auf diese Weise können Sie komplexe und leistungsstarke Regeln erstellen, die beispielsweise nur das Hochladen von Dateien mit bestimmten Inhaltstypen zulassen oder nur das Löschen von Dateien ab einer bestimmten Größe zulassen.

Firebase-Sicherheitsregeln für Cloud Storage stellen Dateimetadaten im resource bereit, das Schlüssel/Wert-Paare der Metadaten enthält, die in einem Cloud Storage-Objekt angezeigt werden. Diese Eigenschaften können bei read oder write überprüft werden, um die Datenintegrität sicherzustellen.

Bei write (z. B. Uploads, Metadatenaktualisierungen und Löschvorgängen) haben Sie zusätzlich zum resource , das Dateimetadaten für die Datei enthält, die derzeit im Anforderungspfad vorhanden ist, auch die Möglichkeit, das Objekt request.resource zu verwenden. die eine Teilmenge der Dateimetadaten enthält, die geschrieben werden sollen, wenn das Schreiben zulässig ist. Sie können diese beiden Werte verwenden, um die Datenintegrität sicherzustellen oder Anwendungsbeschränkungen wie Dateityp oder -größe durchzusetzen.

Eine vollständige Liste der Eigenschaften im resource finden Sie unten:

Eigentum Typ Beschreibung
name Zeichenfolge Der vollständige Name des Objekts
bucket Zeichenfolge Der Name des Buckets, in dem sich dieses Objekt befindet.
generation int Die Google Cloud Storage-Objektgenerierung dieses Objekts.
metageneration int Die Google Cloud Storage-Objektmetagenerierung dieses Objekts.
size int Die Größe des Objekts in Bytes.
timeCreated Zeitstempel Ein Zeitstempel, der den Zeitpunkt angibt, zu dem ein Objekt erstellt wurde.
updated Zeitstempel Ein Zeitstempel, der den Zeitpunkt angibt, zu dem ein Objekt zuletzt aktualisiert wurde.
md5Hash Zeichenfolge Ein MD5-Hash des Objekts.
crc32c Zeichenfolge Ein crc32c-Hash des Objekts.
etag Zeichenfolge Das diesem Objekt zugeordnete Etag.
contentDisposition Zeichenfolge Die diesem Objekt zugeordnete Inhaltsdisposition.
contentEncoding Zeichenfolge Die diesem Objekt zugeordnete Inhaltskodierung.
contentLanguage Zeichenfolge Die diesem Objekt zugeordnete Inhaltssprache.
contentType Zeichenfolge Der diesem Objekt zugeordnete Inhaltstyp.
metadata map<string, string> Schlüssel/Wert-Paare zusätzlicher, vom Entwickler angegebener benutzerdefinierter Metadaten.

request.resource enthält alle diese mit Ausnahme von generation , metageneration , etag , timeCreated und updated .

Erweitern Sie mit Cloud Firestore

Sie können auf Dokumente im Cloud Firestore zugreifen, um andere Autorisierungskriterien auszuwerten.

Mit den Funktionen firestore.get() und firestore.exists() können Ihre Sicherheitsregeln eingehende Anfragen anhand von Dokumenten in Cloud Firestore bewerten. Die Funktionen firestore.get() und firestore.exists() erwarten beide vollständig angegebene Dokumentpfade. Wenn Sie Variablen verwenden, um Pfade für firestore.get() und firestore.exists() zu erstellen, müssen Sie Variablen mithilfe der $(variable) -Syntax explizit maskieren.

Im folgenden Beispiel sehen wir eine Regel, die den Lesezugriff auf Dateien auf Benutzer beschränkt, die Mitglieder bestimmter Clubs sind.

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{club}/files/{fileId} {
      allow read: if club in
        firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships
    }
  }
}
Im nächsten Beispiel können nur die Freunde eines Benutzers seine Fotos sehen.
service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/photos/{fileId} {
      allow read: if
        firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id))
    }
  }
}

Sobald Sie Ihre ersten Cloud Storage-Sicherheitsregeln erstellt und gespeichert haben, die diese Cloud Firestore-Funktionen verwenden, werden Sie in der Firebase-Konsole oder der Firebase-CLI aufgefordert, Berechtigungen zum Verbinden der beiden Produkte zu aktivieren.

Sie können die Funktion deaktivieren, indem Sie eine IAM-Rolle entfernen, wie unter Verwalten und Bereitstellen von Firebase-Sicherheitsregeln beschrieben.

Daten validieren

Firebase-Sicherheitsregeln für Cloud Storage können auch zur Datenvalidierung verwendet werden, einschließlich der Validierung von Dateinamen und -pfad sowie Dateimetadateneigenschaften wie contentType und size .

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

Benutzerdefinierte Funktionen

Wenn Ihre Firebase-Sicherheitsregeln komplexer werden, möchten Sie möglicherweise Sätze von Bedingungen 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 der von JavaScript, die Funktionen von Firebase Security Rules 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 firebase.storage definierte Funktion Zugriff auf die resource und nur für Cloud Firestore auf integrierte Funktionen wie get() und exists() .
  • Funktionen können andere Funktionen aufrufen, dürfen jedoch nicht rekursiv sein. Die Gesamttiefe des Aufrufstapels ist auf 10 begrenzt.
  • In Version rules2 können Funktionen Variablen mithilfe des Schlüsselworts let definieren. Funktionen können eine beliebige Anzahl von 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 firebase.storage {
  match /b/{bucket}/o {
    // 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 /images/{imageId} {
      allow read, write: if signedInOrPublic();
    }
    match /mp3s/{mp3Ids} {
      allow read: if signedInOrPublic();
    }
  }
}

Durch die Verwendung von Funktionen in Ihren Firebase-Sicherheitsregeln werden diese leichter wartbar, wenn die Komplexität Ihrer Regeln zunimmt.

Nächste Schritte

Nach dieser Erörterung der Bedingungen verfügen Sie über ein umfassenderes Verständnis der Regeln und sind bereit für Folgendes:

Erfahren Sie, wie Sie mit Kernanwendungsfällen umgehen und lernen Sie den Workflow zum Entwickeln, Testen und Bereitstellen von Regeln kennen: