Ten przewodnik opiera się na poznawaniu podstawowej składni języka Firebase Security Rules i pokazuje, jak dodać warunki do Firebase Security Rules dla Cloud Storage.
Podstawowym elementem Cloud Storage Security Rules jest warunek. Warunek to wyrażenie logiczne określające, czy dana operacja powinna zostać dozwolona, czy odrzucona. W przypadku podstawowych reguł najlepiej sprawdza się użycie literałów true
i false
. Jednak Firebase Security Rules w języku Cloud Storage umożliwia tworzenie bardziej złożonych warunków, które mogą:
- Sprawdzanie uwierzytelniania użytkowników
- Weryfikuj dane przychodzące
Uwierzytelnianie
Firebase Security Rules dla Cloud Storage integruje się z Firebase Authentication, aby zapewnić Cloud Storage skuteczne uwierzytelnianie użytkowników. Umożliwia to szczegółową kontrolę dostępu na podstawie roszczeń tokena Firebase Authentication.
Gdy uwierzytelniony użytkownik wysyła żądanie do Cloud Storage, zmienna request.auth
jest wypełniana wartością uid
użytkownika (request.auth.uid
), a także deklaracjami tokena JWT Firebase Authentication (request.auth.token
).
Ponadto w przypadku uwierzytelniania niestandardowego w polu request.auth.token
wyświetlają się dodatkowe oświadczenia.
Gdy nieuwierzytelniony użytkownik wysyła żądanie, zmienna request.auth
ma wartość null
.
Korzystając z tych danych, istnieje kilka popularnych sposobów uwierzytelniania do zabezpieczania plików:
- Publiczna: ignoruj użytkownika
request.auth
- Uwierzytelniony dostęp prywatny: sprawdź, czy
request.auth
nie jestnull
- Prywatne informacje o użytkowniku: sprawdź, czy
request.auth.uid
jest równe ścieżceuid
. - Grupa prywatna: sprawdź oświadczenia tokena niestandardowego, aby dopasować wybrane oświadczenie, lub odczytaj metadane pliku, aby sprawdzić, czy istnieje pole metadanych.
Publiczny
Każda reguła, która nie uwzględnia kontekstu request.auth
, może być uznana za regułę public
, ponieważ nie uwzględnia kontekstu uwierzytelniania użytkownika.
Reguły te mogą być przydatne przy udostępnianiu danych publicznych, takich jak zasoby gry, pliki dźwiękowe lub inne treści statyczne.
// 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"); }
Uwierzytelniona prywatna
W niektórych przypadkach możesz chcieć, aby dane były widoczne dla wszystkich uwierzytelnionych użytkowników aplikacji, ale nie dla niezalogowanych użytkowników. Ponieważ zmienna request.auth
ma wartość null
dla wszystkich niezaufanych użytkowników, wystarczy sprawdzić, czy zmienna request.auth
istnieje, aby wymagać uwierzytelnienia:
// Require authentication on all internal image reads match /internal/{imageId} { allow read: if request.auth != null; }
Prywatny użytkownik
Najczęstszym przypadkiem użycia request.auth
będzie przyznanie użytkownikom szczegółowych uprawnień do ich plików: od przesyłania zdjęć profilowych do czytania prywatnych dokumentów.
Ponieważ pliki w Cloud Storage mają pełną „ścieżkę” do pliku, wystarczy, że plik jest kontrolowany przez użytkownika, a w prefiksie nazwy pliku znajduje się unikalny element identyfikujący użytkownika (taki jak uid
użytkownika), który można sprawdzić podczas oceny reguły:
// 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; }
Grupa prywatna
Innym równie często spotykanym przypadkiem użycia jest przyznawanie uprawnień grupie do obiektu, np. umożliwienie kilku członkom zespołu współpracy nad udostępnionym dokumentem. Można to zrobić na kilka sposobów:
- Utwórz token niestandardowy Firebase Authentication, który zawiera dodatkowe informacje o członku grupy (np. identyfikator grupy).
- Uwzględnij informacje o grupie (takie jak identyfikator grupy lub lista autoryzowanych
uid
) w metadanych pliku.
Gdy te dane zostaną zapisane w tokenie lub metadanych pliku, można się do nich odwołać z poziomu reguły:
// 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; }
Poproś o ocenę
Przesyłanie, pobieranie, zmiany metadanych i usuwanie są oceniane za pomocą request
wysłanego do Cloud Storage. Oprócz unikalnego identyfikatora użytkownika i ładunku Firebase Authentication w obiekcie request.auth
, jak opisano powyżej, zmienna request
zawiera ścieżkę do pliku, w którym wykonywane jest żądanie, czas otrzymania żądania i nową wartość resource
, jeśli żądanie dotyczy zapisu.
Obiekt request
zawiera też unikalny identyfikator użytkownika oraz dane Firebase Authentication w obiekcie request.auth
, co zostanie wyjaśnione w sekcji Bezpieczeństwo oparte na użytkowniku w dokumentacji.
Pełna lista właściwości obiektu request
znajduje się poniżej:
Właściwość | Typ | Opis |
---|---|---|
auth |
map<string, string> | Gdy użytkownik jest zalogowany, przekazuje uid , czyli swój unikalny identyfikator, oraz token , czyli mapę Firebase Authentication deklaracji JWT. W przeciwnym razie będzie to:null . |
params |
map<string, string> | Mapa zawierająca parametry zapytania żądania. |
path |
ścieżka | path reprezentujący ścieżkę, na której wykonywane jest żądanie. |
resource |
map<string, string> | Nowa wartość zasobu, obecna tylko w przypadku żądań write .
|
time |
sygnatura czasowa | Znak czasowy określający czas serwera, w którym żądanie zostało ocenione. |
Ocena zasobów
Podczas oceny reguł możesz też ocenić metadane pliku, który jest przesyłany, pobierany, modyfikowany lub usuwany. Dzięki temu możesz tworzyć złożone i skuteczne reguły, które na przykład zezwalają na przesyłanie tylko plików z określonymi typami treści lub usuwanie tylko plików o większym rozmiarze.
Firebase Security Rules dla Cloud Storage udostępnia metadane pliku w obiekcie resource
, który zawiera pary klucz-wartość metadanych wyświetlanych w obiekcie Cloud Storage. Te właściwości można sprawdzić w prośbach read
lub write
, aby zapewnić integralność danych.
W przypadku żądań write
(takich jak przesyłanie, aktualizowanie metadanych i usuwanie) oprócz obiektu resource
, który zawiera metadane pliku znajdującego się obecnie na ścieżce żądania, możesz też użyć obiektu request.resource
, który zawiera podzbiór metadanych pliku do zapisania, jeśli zapis jest dozwolony. Możesz użyć tych 2 wartości, aby zapewnić integralność danych lub zastosować ograniczenia aplikacji, takie jak typ lub rozmiar pliku.
Pełna lista właściwości obiektu resource
znajduje się poniżej:
Właściwość | Typ | Opis |
---|---|---|
name |
ciąg znaków | Pełna nazwa obiektu |
bucket |
ciąg znaków | Nazwa zasobnika, w którym znajduje się ten obiekt. |
generation |
int, | Google Cloud Storage generacja obiektu tego obiektu. |
metageneration |
int, | Metageneracja obiektu Google Cloud Storage tego obiektu. |
size |
int, | Rozmiar obiektu w bajtach. |
timeCreated |
sygnatura czasowa | Sygnatura czasowa reprezentująca czas utworzenia obiektu. |
updated |
sygnatura czasowa | Sygnatura czasowa określająca, kiedy obiekt został ostatnio zaktualizowany. |
md5Hash |
ciąg znaków | Skrót MD5 obiektu. |
crc32c |
ciąg znaków | Hasz CRC32C obiektu. |
etag |
ciąg znaków | ETag powiązany z tym obiektem. |
contentDisposition |
ciąg znaków | Ustawienie treści powiązane z tym obiektem. |
contentEncoding |
ciąg znaków | Kodowanie treści powiązane z tym obiektem. |
contentLanguage |
ciąg znaków | Język treści powiązany z tym obiektem. |
contentType |
ciąg znaków | Typ treści powiązany z tym obiektem. |
metadata |
map<string, string> | Pary klucz-wartość dodatkowych metadanych niestandardowych określonych przez dewelopera. |
request.resource
zawiera wszystkie te opcje oprócz generation
,
metageneration
, etag
, timeCreated
i updated
.
Ulepsz za pomocą Cloud Firestore
Aby sprawdzić inne kryteria autoryzacji, możesz uzyskać dostęp do dokumentów w Cloud Firestore.
Dzięki funkcjom firestore.get()
i firestore.exists()
reguły bezpieczeństwa mogą sprawdzać przychodzące żądania pod kątem dokumentów w Cloud Firestore.
Funkcje firestore.get()
i firestore.exists()
oczekują w pełni określonych ścieżek dokumentu. Jeśli do tworzenia ścieżek dla firestore.get()
i firestore.exists()
używasz zmiennych, musisz za pomocą składni $(variable)
wyraźnie zmienić znaczenie zmiennych.
W przykładzie poniżej widzimy regułę, która ogranicza dostęp do odczytu plików do użytkowników należących do określonych klubów.
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 } } }
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)) } } }
Gdy utworzysz i zapiszesz pierwszy Cloud Storage Security Rules, który używa tych funkcji Cloud Firestore, w konsoli Firebase lub w interfejsie wiersza poleceń Firebase pojawi się prośba o włączenie uprawnień umożliwiających połączenie tych dwóch usług.
Możesz wyłączyć tę funkcję, usuwając rolę uprawnień zgodnie z opisem w artykule Wdrażanie usługi Firebase Security Rules i zarządzanie nią.
Sprawdzanie danych
Firebase Security Rules dla Cloud Storage może też służyć do weryfikacji danych, w tym do weryfikacji nazwy i ścieżki pliku, a także właściwości metadanych pliku, np. contentType
i 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/.*'); } } }
Funkcje niestandardowe
W miarę jak reguły Firebase Security Rules stają się bardziej złożone, warto umieszczać zbiory warunków w funkcjach, które można używać wielokrotnie w ramach reguł. Reguły zabezpieczeń obsługują funkcje niestandardowe. Składnia funkcji niestandardowych jest podobna do składni języka JavaScript, ale funkcje Firebase Security Rules są pisane w języku specyficznym dla danej dziedziny, który ma pewne ważne ograniczenia:
- Funkcje mogą zawierać tylko jedno wyrażenie
return
. Nie mogą zawierać żadnej dodatkowej logiki. Nie mogą np. uruchamiać pętli ani wywoływać usług zewnętrznych. - Funkcje mogą automatycznie uzyskiwać dostęp do funkcji i zmiennych z zakresu, w którym są zdefiniowane. Na przykład funkcja zdefiniowana w zakresie
service firebase.storage
ma dostęp do zmiennejresource
, a tylko w zakresie Cloud Firestore – do funkcji wbudowanych, takich jakget()
iexists()
. - Funkcje mogą wywoływać inne funkcje, ale nie mogą być rekurencyjne. Łączna głębokość wywołania zasobnika jest ograniczona do 10.
- W wersji
rules2
funkcje mogą definiować zmienne za pomocą słowa kluczowegolet
. Funkcje mogą zawierać dowolną liczbę instrukcji let, ale muszą kończyć się instrukcją return.
Funkcja jest definiowana za pomocą słowa kluczowego function
i przyjmuje od 0 do nieograniczonej liczby argumentów. Możesz na przykład połączyć 2 rodzaje warunków użytych w powyższych przykładach w jedną funkcję:
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();
}
}
}
Używanie funkcji w definicji Firebase Security Rules ułatwia ich utrzymanie, gdy reguły stają się coraz bardziej złożone.
Dalsze kroki
Po tej dyskusji na temat warunków masz już większą wiedzę na temat reguł i możesz:
Dowiedz się, jak obsługiwać podstawowe przypadki użycia i jak wygląda proces tworzenia, testowania i wdrażania reguł:
- Utwórz reguły, które będą odpowiadać typowym scenariuszom.
- Poszerz swoją wiedzę, analizując sytuacje, w których musisz wykrywać i unikać niepewnych reguł.
- Testuj reguły za pomocą emulatora Cloud Storage i dedykowanej biblioteki testów reguł zabezpieczeń.
- Zapoznaj się z dostępnymi metodami wdrażania Rules.