Dieser Leitfaden baut auf dem Erlernen der Kernsyntax des Sprachleitfadens zu Firebase-Sicherheitsregeln auf, um zu zeigen, wie Sie Bedingungen zu Ihren Firebase-Sicherheitsregeln für Cloud Storage hinzufügen.
Der primäre Baustein der Cloud Storage-Sicherheitsregeln ist die Bedingung . Eine Bedingung ist ein boolescher Ausdruck, der festlegt, ob eine bestimmte Operation zugelassen oder verweigert werden soll. Für grundlegende Regeln funktioniert die Verwendung von true
und false
Literalen als Bedingungen sehr 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
- Validieren Sie eingehende Daten
Authentifizierung
Firebase-Sicherheitsregeln für Cloud Storage lassen sich in die Firebase-Authentifizierung integrieren, um eine leistungsstarke benutzerbasierte Authentifizierung für Cloud Storage bereitzustellen. Dies ermöglicht eine granulare 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-Authentifizierungs-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
nichtnull
ist - Benutzer privat: Überprüfen Sie, ob
request.auth.uid
einer Pfad-uid
entspricht - Gruppe privat: Überprüfen Sie die Ansprüche des benutzerdefinierten Tokens auf Übereinstimmung mit einem ausgewählten Anspruch, oder lesen Sie die Metadaten der Datei, um festzustellen, ob ein Metadatenfeld vorhanden ist
Öffentlich
Jede Regel, die den Kontext request.auth
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 Spielinhalte, 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"); }
Authentifiziert privat
In bestimmten Fällen möchten Sie möglicherweise, dass Daten von allen authentifizierten Benutzern Ihrer Anwendung angezeigt werden können, nicht jedoch von nicht authentifizierten Benutzern. Da die Variable request.auth
für alle nicht authentifizierten Benutzer null
ist, müssen Sie nur überprüfen, ob die Variable „ request.auth
vorhanden ist, um eine Authentifizierung zu verlangen:
// 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 granulare Berechtigungen für ihre Dateien zu erteilen: vom Hochladen von Profilbildern bis zum Lesen privater Dokumente.
Da Dateien in Cloud Storage einen vollständigen "Pfad" zu der Datei haben, ist alles, was erforderlich ist, um eine Datei zu erstellen, die von einem Benutzer kontrolliert wird, eine eindeutige, den Benutzer identifizierende Information im Dateinamenprä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, z. B. mehreren Teammitgliedern die Zusammenarbeit an einem freigegebenen Dokument zu ermöglichen. Dazu gibt es mehrere Ansätze:
- Erstellen Sie ein benutzerdefiniertes Token für die Firebase-Authentifizierung, das zusätzliche Informationen über ein 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 in den Token- oder 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 Nutzlast der Firebase-Authentifizierung im Objekt request.auth
, wie oben beschrieben, enthält die request
den Dateipfad, in dem die Anfrage ausgeführt wird, die Uhrzeit, zu der die Anfrage empfangen wird, und den neuen resource
if die Anforderung ist ein Schreiben.
Das request
enthält auch die eindeutige ID des Benutzers und die Nutzdaten der Firebase-Authentifizierung im Objekt „ request.auth
“, die im Abschnitt „Benutzerbasierte Sicherheit“ der Dokumentation näher erläutert werden.
Eine vollständige Liste der Eigenschaften im request
ist unten verfügbar:
Eigentum | Typ | Beschreibung |
---|---|---|
auth | map<Zeichenfolge, Zeichenfolge> | Wenn ein Benutzer angemeldet ist, werden uid , die eindeutige ID des Benutzers, und token , eine Zuordnung von JWT-Ansprüchen für die Firebase-Authentifizierung, bereitgestellt. Andernfalls ist es null . |
params | map<Zeichenfolge, Zeichenfolge> | Map mit den Abfrageparametern der Anfrage. |
path | Weg | Ein path , der den Pfad darstellt, auf dem die Anforderung ausgeführt wird. |
resource | map<Zeichenfolge, Zeichenfolge> | Der neue Ressourcenwert, der nur bei write vorhanden ist. |
time | Zeitstempel | Ein Zeitstempel, der die Serverzeit darstellt, 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 das Hochladen von Dateien mit bestimmten Inhaltstypen zulassen oder nur das Löschen von Dateien, die eine bestimmte Größe überschreiten.
Firebase Security Rules for Cloud Storage stellt 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, Aktualisierungen von Metadaten und Löschungen) 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 zu schreibenden Dateimetadaten enthält, wenn das Schreiben erlaubt ist. Sie können diese beiden Werte verwenden, um die Datenintegrität sicherzustellen oder Anwendungseinschränkungen wie Dateityp oder -größe durchzusetzen.
Eine vollständige Liste der Eigenschaften im resource
ist unten verfügbar:
Eigentum | Typ | Beschreibung |
---|---|---|
name | Schnur | Der vollständige Name des Objekts |
bucket | Schnur | Der Name des Buckets, in dem sich dieses Objekt befindet. |
generation | int | Die Google Cloud Storage-Objektgenerierung dieses Objekts. |
metageneration | int | Die Metagenerierung des Google Cloud Storage-Objekts dieses Objekts. |
size | int | Die Größe des Objekts in Bytes. |
timeCreated | Zeitstempel | Ein Zeitstempel, der die Zeit darstellt, zu der ein Objekt erstellt wurde. |
updated | Zeitstempel | Ein Zeitstempel, der die Zeit darstellt, zu der ein Objekt zuletzt aktualisiert wurde. |
md5Hash | Schnur | Ein MD5-Hash des Objekts. |
crc32c | Schnur | Ein crc32c-Hash des Objekts. |
etag | Schnur | Das diesem Objekt zugeordnete Etag. |
contentDisposition | Schnur | Die Inhaltsdisposition, die diesem Objekt zugeordnet ist. |
contentEncoding | Schnur | Die diesem Objekt zugeordnete Inhaltscodierung. |
contentLanguage | Schnur | Die diesem Objekt zugeordnete Inhaltssprache. |
contentType | Schnur | Der diesem Objekt zugeordnete Inhaltstyp. |
metadata | map<Zeichenfolge, Zeichenfolge> | Schlüssel/Wert-Paare zusätzlicher, vom Entwickler angegebener benutzerdefinierter Metadaten. |
request.resource
enthält all diese mit Ausnahme von generation
, metageneration
, etag
, timeCreated
und updated
.
Verbessern Sie mit Cloud Firestore
Sie können auf Dokumente in Cloud Firestore zugreifen, um andere Autorisierungskriterien zu bewerten.
Mithilfe der Funktionen firestore.get()
und firestore.exists()
können Ihre Sicherheitsregeln eingehende Anfragen anhand von Dokumenten in Cloud Firestore auswerten. 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 explizit mit der $(variable)
-Syntax maskieren.
Im folgenden Beispiel sehen wir eine Regel, die den Lesezugriff auf Dateien auf die 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 ihre 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)) } } }
Nachdem 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-Befehlszeilenschnittstelle 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 -pfaden 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 immer komplexer werden, möchten Sie möglicherweise Bedingungssätze in Funktionen verpacken, die Sie in Ihrem Regelsatz wiederverwenden können. Sicherheitsregeln unterstützen benutzerdefinierte Funktionen. Die Syntax für benutzerdefinierte Funktionen ähnelt ein wenig JavaScript, aber die Funktionen der Firebase-Sicherheitsregeln sind 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 Gültigkeitsbereich zugreifen, in dem sie definiert sind. Beispielsweise hat eine im Bereich
service firebase.storage
definierte Funktion Zugriff auf dieresource
und nur für Cloud Firestore auf integrierte Funktionen wieget()
exists()
. - Funktionen können andere Funktionen aufrufen, dürfen aber nicht rekursiv sein. Die gesamte Call-Stack-Tiefe ist auf 10 begrenzt.
- In
rules2
können Funktionen Variablen mit dem Schlüsselwortlet
definieren. Funktionen können beliebig viele Let-Bindungen haben, müssen aber 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 Arten von Bedingungen, die in den obigen Beispielen verwendet werden, 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();
}
}
}
Die Verwendung von Funktionen in Ihren Firebase-Sicherheitsregeln macht sie wartungsfreundlicher, wenn die Komplexität Ihrer Regeln zunimmt.
Nächste Schritte
Nach dieser Erörterung der Bedingungen haben Sie ein differenzierteres Verständnis der Regeln und sind bereit:
Erfahren Sie, wie Sie mit Kernanwendungsfällen umgehen, und lernen Sie den Arbeitsablauf zum Entwickeln, Testen und Bereitstellen von Regeln kennen:
- Schreiben Sie Regeln für gängige Szenarien .
- Bauen Sie auf Ihrem Wissen auf, indem Sie Situationen überprüfen, in denen Sie unsichere Regeln erkennen und vermeiden müssen.
- Testen Sie Regeln mit dem Cloud Storage-Emulator und der dedizierten Testbibliothek für Sicherheitsregeln .
- Sehen Sie sich die verfügbaren Methoden zum Bereitstellen von Regeln an.