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

Ten przewodnik opiera się na podstawowej składni przewodnika językowego Firebase Security Rules i pokazuje, jak dodawać warunki do reguł zabezpieczeń Firebase dla Cloud Storage.

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

  • Sprawdź uwierzytelnienie użytkownika
  • Zweryfikuj przychodzące dane

Uwierzytelnianie

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

Gdy uwierzytelniony użytkownik wysyła żądanie do Cloud Storage, zmienna request.auth jest wypełniana uid użytkownika użytkownika ( request.auth.uid ), a także oświadczeniami tokenu JWT uwierzytelniania Firebase ( request.auth.token ).

Ponadto w przypadku korzystania z uwierzytelniania niestandardowego w polu request.auth.token pojawiają się dodatkowe oświadczenia.

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

Korzystając z tych danych, istnieje kilka popularnych sposobów korzystania z uwierzytelniania w celu zabezpieczenia plików:

  • Publiczne: zignoruj request.auth
  • Uwierzytelniony prywatny: sprawdź, czy request.auth nie ma null
  • Użytkownik prywatny: sprawdź, czy request.auth.uid jest równy identyfikatorowi użytkownika uid
  • Grupa prywatna: sprawdź oświadczenia tokena niestandardowego, aby pasowały do ​​wybranego roszczenia lub przeczytaj metadane pliku, aby sprawdzić, czy pole metadanych istnieje

Publiczny

Każdą regułę, która nie uwzględnia kontekstu request.auth , można uznać za regułę public , ponieważ nie uwzględnia ona kontekstu uwierzytelniania użytkownika. Reguły te mogą być przydatne do ujawniania danych publicznych, takich jak zasoby gier, pliki dźwiękowe lub inna zawartość statyczna.

// 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");
}

Uwierzytelnione prywatne

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, 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;
}

Użytkownik prywatny

Zdecydowanie najczęstszym przypadkiem użycia request.auth będzie zapewnienie indywidualnym 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, aby plik był kontrolowany przez użytkownika, wystarczy informacja identyfikująca użytkownika w przedrostku nazwy pliku (taka jak uid użytkownika), którą 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 częstym przypadkiem użycia będzie zezwolenie na uprawnienia grupowe do obiektu, na przykład zezwolenie kilku członkom zespołu na współpracę nad udostępnionym dokumentem. Można to zrobić na kilka sposobów:

  • Wytwórz niestandardowy token uwierzytelniania Firebase, który zawiera dodatkowe informacje o członku grupy (takie jak identyfikator grupy)
  • Uwzględnij informacje o grupie (takie jak identyfikator grupy lub lista autoryzowanych uid ) w metadanych pliku

Po zapisaniu tych danych w metadanych tokenu lub 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 usunięcia są oceniane na podstawie request wysył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 żądanie jest wykonywane, godzinę otrzymania żądania oraz nową wartość resource , jeśli prośba jest pisemna.

Obiekt request zawiera także unikalny identyfikator użytkownika i ładunek Firebase Authentication w obiekcie request.auth , co zostanie wyjaśnione szczegółowo w sekcji dokumentacji dotyczącej zabezpieczeń opartych na użytkownikach .

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

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

Ocena zasobów

Oceniając reguły, możesz także chcieć ocenić metadane przesyłanego, pobieranego, modyfikowanego lub usuwanego pliku. Umożliwia to tworzenie złożonych i wydajnych reguł, które na przykład zezwalają 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 zabezpieczeń Firebase dla Cloud Storage udostępniają metadane pliku w obiekcie resource , który zawiera pary klucz/wartość metadanych wyświetlanych w obiekcie Cloud Storage. Właściwości te można sprawdzić w żądaniach 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 istniejącego aktualnie w ścieżce żądania, masz także możliwość wykorzystania obiektu request.resource , który zawiera podzbiór metadanych pliku, który ma zostać zapisany, 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 dostępna jest poniżej:

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

request.resource zawiera 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.

Dzięki funkcjom firestore.get() i firestore.exists() reguły bezpieczeństwa mogą oceniać 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 dokumentów. Używając zmiennych do konstruowania ścieżek dla firestore.get() i firestore.exists() , musisz jawnie uciec od zmiennych, używając składni $(variable) .

W poniższym przykładzie widzimy regułę ograniczającą dostęp do odczytu plików tylko użytkownikom będącym 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 korzystających z funkcji Cloud Firestore zostaniesz poproszony w konsoli Firebase lub interfejsie CLI Firebase o włączenie uprawnień do połączenia obu produktów.

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

Zweryfikuj dane

Reguł bezpieczeństwa Firebase dla Cloud Storage można również używać do sprawdzania poprawności danych, w tym sprawdzania 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 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 całym zestawie reguł. Reguły bezpieczeństwa obsługują funkcje niestandardowe. Składnia funkcji niestandardowych przypomina trochę JavaScript, ale funkcje reguł bezpieczeństwa Firebase są napisane 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 ma wbudowane funkcje, takie 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. Możesz na przykład połączyć dwa typy warunków użyte 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();
    }
  }
}

Korzystanie z funkcji w regułach bezpieczeństwa Firebase sprawia, że ​​są one łatwiejsze w utrzymaniu w miarę wzrostu złożoności reguł.

Następne kroki

Po omówieniu warunków masz bardziej wyrafinowane zrozumienie Reguł 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ł: