Użyj warunków w Regułach bezpieczeństwa Firebase Cloud Storage

Ten przewodnik opiera się na podstawowej składni przewodnika językowego Reguły bezpieczeństwa Firebase, aby pokazać, jak dodać warunki do Reguł bezpieczeństwa Firebase dla Cloud Storage.

Podstawowym elementem składowym Reguł bezpieczeństwa Cloud Storage jest warunek . Warunek to wyrażenie logiczne określające, czy dana operacja powinna być dozwolona, ​​czy zabroniona. W przypadku podstawowych reguł używanie true i false literałów jako warunków działa doskonale. Jednak język Firebase Security Rules for Cloud Storage umożliwia pisanie bardziej złożonych warunków, które mogą:

  • Sprawdź uwierzytelnianie użytkownika
  • Weryfikuj dane przychodzące

Uwierzytelnianie

Reguły bezpieczeństwa Firebase dla Cloud Storage integrują się z uwierzytelnianiem Firebase, aby zapewnić wydajne uwierzytelnianie oparte na użytkownikach w Cloud Storage. Pozwala to na szczegółową kontrolę dostępu na podstawie roszczeń tokena uwierzytelniania Firebase.

Gdy uwierzytelniony użytkownik wysyła żądanie do Cloud Storage, zmienna request.auth jest wypełniana uid użytkownika ( request.auth.uid ) oraz żądaniami tokenu uwierzytelniania Firebase ( request.auth.token ).

Ponadto w przypadku korzystania z uwierzytelniania niestandardowego w polu request.auth.token są wyświetlane dodatkowe oświadczenia.

Gdy nieuwierzytelniony użytkownik wykonuje żądanie, zmienna request.auth ma wartość null .

Korzystając z tych danych, istnieje kilka typowych sposobów używania uwierzytelniania do zabezpieczania plików:

  • Publiczny: zignoruj request.auth
  • Uwierzytelniony prywatny: sprawdź, czy request.auth nie ma null
  • Prywatny użytkownik: sprawdź, czy request.auth.uid jest równe identyfikatorowi uid
  • Grupuj prywatnie: sprawdź roszczenia niestandardowego tokena, aby pasowały do ​​wybranego roszczenia, lub przeczytaj metadane pliku, aby zobaczyć, 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 w przypadku udostępniania 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");
}

Uwierzytelniony prywatny

W niektórych przypadkach możesz chcieć, aby dane były widoczne dla wszystkich uwierzytelnionych użytkowników Twojej aplikacji, ale nie dla użytkowników nieuwierzytelnionych. Ponieważ zmienna request.auth ma null dla wszystkich nieuwierzytelnionych użytkowników, wszystko, co musisz zrobić, to 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;
}

Użytkownik prywatny

Zdecydowanie najczęstszym przypadkiem użycia request.auth będzie nadanie poszczególnym użytkownikom szczegółowych uprawnień do ich plików: od przesyłania zdjęć profilowych po czytanie prywatnych dokumentów.

Ponieważ pliki w Cloud Storage mają pełną „ścieżkę” do pliku, wszystko, czego potrzeba, aby plik był kontrolowany przez użytkownika, to unikatowe informacje identyfikujące użytkownika w prefiksie nazwy pliku (takie jak uid użytkownika), które można sprawdzić kiedy reguła jest oceniana:

// 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 powszechnym przypadkiem użycia będzie przyznanie uprawnień grupowych do obiektu, na przykład umożliwienie kilku członkom zespołu współpracy nad udostępnionym dokumentem. Można to zrobić na kilka sposobów:

  • Utwórz niestandardowy token Firebase Authentication, który zawiera dodatkowe informacje o członku grupy (takie jak identyfikator grupy)
  • Dołącz informacje o grupie (takie jak identyfikator grupy lub lista autoryzowanych uid ) w metadanych pliku

Gdy te dane są przechowywane w tokenie lub metadanych pliku, można się do nich odwoływać 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 na podstawie request wysyłanego do Cloud Storage. Oprócz unikalnego identyfikatora użytkownika i ładunku uwierzytelniania Firebase w obiekcie request.auth , jak opisano powyżej, zmienna request zawiera ścieżkę do pliku, w którym żądanie jest wykonywane, czas otrzymania żądania oraz nową wartość resource , jeśli prośba jest pisemna.

Obiekt request zawiera również unikalny identyfikator użytkownika i ładunek uwierzytelniania Firebase w obiekcie request.auth , co zostanie dokładniej wyjaśnione w sekcji Zabezpieczenia oparte na użytkownikach w dokumentacji.

Pełna lista właściwości w obiekcie request jest dostępna poniżej:

Nieruchomość Typ Opis
auth map<łańcuch, ciąg> Gdy użytkownik jest zalogowany, podaje uid , unikalny identyfikator użytkownika i token , mapę oświadczeń JWT uwierzytelniania Firebase. W przeciwnym razie będzie to null .
params map<łańcuch, ciąg> Mapa zawierająca parametry zapytania żądania.
path ścieżka path reprezentująca ścieżkę, w której wykonywane jest żądanie.
resource map<łańcuch, ciąg> Nowa wartość zasobu, obecna tylko w żądaniach write .
time znak czasu Sygnatura czasowa reprezentująca czas serwera, w którym żądanie jest oceniane.

Ocena zasobów

Oceniając reguły, możesz również chcieć ocenić metadane przesyłanego, pobieranego, modyfikowanego lub usuwanego pliku. Pozwala to na tworzenie złożonych i zaawansowanych reguł, które pozwalają np. zezwalać na przesyłanie tylko plików o określonym typie zawartości lub usuwanie tylko plików większych niż określony rozmiar.

Reguły bezpieczeństwa Firebase dla Cloud Storage udostępniają metadane pliku w obiekcie resource , który zawiera pary klucz/wartość metadanych udostępnianych w obiekcie Cloud Storage. Te właściwości można sprawdzać podczas żądań read lub write , aby zapewnić integralność danych.

W przypadku żądań write (takich jak przesyłanie, aktualizacja metadanych i usuwanie) oprócz obiektu resource , który zawiera metadane pliku aktualnie istniejącego w ścieżce żądania, masz również możliwość użycia obiektu request.resource , który zawiera podzbiór metadanych pliku do zapisania, jeśli zapis jest dozwolony. Możesz użyć tych dwóch wartości, aby zapewnić integralność danych lub wymusić ograniczenia aplikacji, takie jak typ lub rozmiar pliku.

Pełna lista właściwości w obiekcie resource jest dostępna poniżej:

Nieruchomość Typ Opis
name strunowy Pełna nazwa obiektu
bucket strunowy Nazwa zasobnika, w którym znajduje się ten obiekt.
generation int Generowanie obiektu Google Cloud Storage dla tego obiektu.
metageneration int Metageneracja obiektu Google Cloud Storage tego obiektu.
size int Rozmiar obiektu w bajtach.
timeCreated znak czasu Sygnatura czasowa reprezentująca czas utworzenia obiektu.
updated znak czasu Sygnatura czasowa reprezentująca czas ostatniej aktualizacji obiektu.
md5Hash strunowy Skrót MD5 obiektu.
crc32c strunowy Skrót crc32c obiektu.
etag strunowy Etag powiązany z tym obiektem.
contentDisposition strunowy Dyspozycja zawartości powiązana z tym obiektem.
contentEncoding strunowy Kodowanie treści skojarzone z tym obiektem.
contentLanguage strunowy Język zawartości powiązany z tym obiektem.
contentType strunowy Typ zawartości skojarzony z tym obiektem.
metadata map<łańcuch, ciąg> Pary klucz/wartość dodatkowych, określonych przez programistę niestandardowych metadanych.

request.resource zawiera je wszystkie z wyjątkiem generation , metageneration , etag , timeCreated i updated .

Ulepsz dzięki Cloud Firestore

Możesz uzyskać dostęp do dokumentów w Cloud Firestore, aby ocenić inne kryteria autoryzacji.

Korzystając z funkcji firestore.get() i firestore.exists() , Twoje reguły bezpieczeństwa mogą oceniać przychodzące żądania względem dokumentów w Cloud Firestore. Funkcje firestore.get() i firestore.exists() oczekują w pełni określonych ścieżek do dokumentów. Używając zmiennych do konstruowania ścieżek dla firestore.get() i firestore.exists() , musisz jawnie uciec przed zmiennymi przy użyciu składni $(variable) .

W poniższym przykładzie widzimy regułę, która ogranicza dostęp do odczytu plików do użytkowników, którzy są członkami poszczególnych 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
    }
  }
}
W następnym przykładzie tylko znajomi użytkownika mogą zobaczyć jego zdjęcia.
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))
    }
  }
}

Po utworzeniu i zapisaniu pierwszych reguł bezpieczeństwa Cloud Storage, które korzystają z tych funkcji Cloud Firestore, w konsoli Firebase lub interfejsie wiersza polecenia Firebase zostanie wyświetlony monit o przyznanie uprawnień do połączenia tych dwóch produktów.

Możesz wyłączyć tę funkcję, usuwając rolę IAM, zgodnie z opisem w artykule Zarządzanie i wdrażanie reguł bezpieczeństwa Firebase .

Zweryfikuj dane

Reguły bezpieczeństwa Firebase dla Cloud Storage mogą być również używane do sprawdzania poprawności danych, w tym sprawdzania poprawności nazwy i ścieżki pliku, a także właściwości metadanych pliku, takich jak 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 Twoje reguły bezpieczeństwa Firebase stają się coraz bardziej złożone, możesz chcieć zawrzeć zestawy warunków w funkcjach, których możesz ponownie używać w swoim zestawie reguł. Reguły bezpieczeństwa obsługują funkcje niestandardowe. Składnia funkcji niestandardowych jest trochę podobna do języka JavaScript, ale funkcje Reguł bezpieczeństwa Firebase są zapisywane w języku specyficznym dla domeny, który ma pewne ważne ograniczenia:

  • Funkcje mogą zawierać tylko jedną instrukcję return . Nie mogą zawierać żadnej dodatkowej logiki. Na przykład nie mogą wykonywać pętli ani wywoływać usług zewnętrznych.
  • Funkcje mogą automatycznie uzyskiwać dostęp do funkcji i zmiennych z zakresu, w którym zostały zdefiniowane. Na przykład funkcja zdefiniowana w zakresie service firebase.storage ma dostęp do zmiennej resource , a tylko w przypadku Cloud Firestore do wbudowanych funkcji, takich jak get() i exists() .
  • Funkcje mogą wywoływać inne funkcje, ale nie mogą się powtarzać. Całkowita głębokość stosu wywołań jest ograniczona do 10.
  • W wersji rules2 funkcje mogą definiować zmienne za pomocą słowa kluczowego let . Funkcje mogą mieć dowolną liczbę powiązań let, ale muszą kończyć się instrukcją return.

Funkcja jest definiowana za pomocą słowa kluczowego function i przyjmuje zero lub więcej argumentów. Na przykład możesz chcieć połączyć dwa typy 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 Regułach bezpieczeństwa Firebase ułatwia ich konserwację wraz ze wzrostem złożoności reguł.

Następne kroki

Po tym omówieniu warunków masz bardziej wyrafinowane zrozumienie zasad i jesteś gotowy do:

Dowiedz się, jak radzić sobie z podstawowymi przypadkami użycia i poznaj przepływ pracy podczas opracowywania, testowania i wdrażania reguł: