Struktura reguł bezpieczeństwa Cloud Firestore

Reguły bezpieczeństwa Cloud Firestore pozwalają kontrolować dostęp do dokumentów i zbiorów w Twojej bazie danych. Elastyczna składnia reguł umożliwia tworzenie reguł pasujących do wszystkiego, od wszystkich zapisów do całej bazy danych po operacje na konkretnym dokumencie.

W tym przewodniku opisano podstawową składnię i strukturę reguł bezpieczeństwa. Połącz tę składnię z warunkami reguł bezpieczeństwa, aby utworzyć kompletne zestawy reguł.

Deklaracja usług i baz danych

Reguły bezpieczeństwa Cloud Firestore zawsze zaczynają się od następującej deklaracji:

service cloud.firestore {
  match /databases/{database}/documents {
    // ...
  }
}

Deklaracja service cloud.firestore obejmuje reguły Cloud Firestore, zapobiegając konfliktom między regułami bezpieczeństwa Cloud Firestore a regułami dotyczącymi innych produktów, takich jak Cloud Storage.

Deklaracja match /databases/{database}/documents określa, że ​​reguły powinny pasować do dowolnej bazy danych Cloud Firestore w projekcie. Obecnie każdy projekt ma tylko jedną bazę danych o nazwie (default) .

Podstawowe zasady odczytu/zapisu

Podstawowe reguły składają się z instrukcji match określającej ścieżkę dokumentu oraz wyrażenia allow określającego, kiedy dozwolone jest odczytywanie określonych danych:

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

Wszystkie instrukcje dopasowania powinny wskazywać na dokumenty, a nie kolekcje. Instrukcja match może wskazywać konkretny dokument, jak w przypadku match /cities/SF lub używać symboli wieloznacznych, aby wskazywać dowolny dokument w określonej ścieżce, jak w przypadku match /cities/{city} .

W powyższym przykładzie instrukcja match używa składni wieloznacznej {city} . Oznacza to, że reguła dotyczy dowolnego dokumentu w kolekcji cities , takiego jak /cities/SF lub /cities/NYC . Po ocenie wyrażeń allow w instrukcji match zmienna city zostanie zamieniona na nazwę dokumentu miasta, na przykład SF lub NYC .

Operacje granularne

W niektórych sytuacjach przydatne jest podzielenie read i write na bardziej szczegółowe operacje. Na przykład Twoja aplikacja może chcieć wymusić inne warunki podczas tworzenia dokumentu niż przy jego usuwaniu. Możesz też zezwolić na odczyt pojedynczych dokumentów, ale zabronić dużych zapytań.

Regułę read można podzielić na get i list , natomiast regułę write można podzielić na create , update i delete :

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
}

Dane hierarchiczne

Dane w Cloud Firestore są zorganizowane w kolekcje dokumentów, a każdy dokument może rozszerzać hierarchię poprzez podzbiory. Ważne jest, aby zrozumieć, w jaki sposób reguły bezpieczeństwa współdziałają z danymi hierarchicznymi.

Rozważmy sytuację, w której każdy dokument w kolekcji cities zawiera podkolekcję landmarks . Reguły bezpieczeństwa obowiązują tylko na dopasowanej ścieżce, więc kontrola dostępu zdefiniowana w kolekcji cities nie ma zastosowania do podkolekcji landmarks . Zamiast tego napisz jawne reguły kontrolujące dostęp do podkolekcji:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

Podczas zagnieżdżania instrukcji match ścieżka wewnętrznej instrukcji match jest zawsze określana względem ścieżki zewnętrznej instrukcji match . Dlatego następujące zestawy reguł są równoważne:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

Rekurencyjne symbole wieloznaczne

Jeśli chcesz, aby reguły miały zastosowanie do dowolnie głębokiej hierarchii, użyj rekurencyjnej składni wieloznacznej, {name=**} . Na przykład:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

W przypadku stosowania rekurencyjnej składni symboli wieloznacznych zmienna wieloznaczna będzie zawierać cały pasujący segment ścieżki, nawet jeśli dokument znajduje się w głęboko zagnieżdżonej kolekcji podrzędnej. Na przykład reguły wymienione powyżej będą pasować do dokumentu znajdującego się w /cities/SF/landmarks/coit_tower , a wartość zmiennej document będzie wynosić SF/landmarks/coit_tower .

Należy jednak pamiętać, że zachowanie rekurencyjnych symboli wieloznacznych zależy od wersji reguł.

Wersja 1

Reguły bezpieczeństwa domyślnie korzystają z wersji 1. W wersji 1 rekursywne symbole wieloznaczne dopasowują jeden lub więcej elementów ścieżki. Nie odpowiadają one pustej ścieżce, więc match /cities/{city}/{document=**} dopasowuje dokumenty w podkolekcjach, ale nie w kolekcji cities , natomiast match /cities/{document=**} dopasowuje oba dokumenty w kolekcji kolekcja i podkolekcja cities .

Rekurencyjne symbole wieloznaczne muszą znajdować się na końcu instrukcji dopasowania.

Wersja 2

W wersji 2 reguł bezpieczeństwa rekurencyjne symbole wieloznaczne dopasowują zero lub więcej elementów ścieżki. match/cities/{city}/{document=**} dopasowuje dokumenty w dowolnych podkolekcjach, a także dokumenty w kolekcji cities .

Musisz wyrazić zgodę na wersję 2, dodając rules_version = '2'; na górze reguł bezpieczeństwa:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

Na instrukcję dopasowania możesz mieć maksymalnie jeden rekurencyjny symbol wieloznaczny, ale w wersji 2 możesz umieścić ten symbol wieloznaczny w dowolnym miejscu instrukcji dopasowania. Na przykład:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

Jeśli używasz zapytań do grup kolekcji , musisz użyć wersji 2, zobacz zabezpieczanie zapytań do grup kolekcji .

Nakładające się instrukcje dopasowania

Możliwe jest, że dokument będzie pasował do więcej niż jednej instrukcji match . W przypadku, gdy do żądania pasuje wiele wyrażeń allow , dostęp jest dozwolony, jeśli true jest którykolwiek z warunków:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

W powyższym przykładzie wszystkie odczyty i zapisy w kolekcji cities będą dozwolone, ponieważ druga reguła jest zawsze true , nawet jeśli pierwsza reguła jest zawsze false .

Limity reguł bezpieczeństwa

Pracując z regułami bezpieczeństwa, należy zwrócić uwagę na następujące ograniczenia:

Limit Detale
Maksymalna liczba wywołań exists() , get() i getAfter() na żądanie
  • 10 w przypadku żądań pojedynczych dokumentów i zapytań.
  • 20 dla odczytów wielu dokumentów, transakcji i zapisów wsadowych. Do każdej operacji obowiązuje również poprzedni limit 10.

    Załóżmy na przykład, że tworzysz zbiorcze żądanie zapisu z 3 operacjami zapisu i że Twoje reguły bezpieczeństwa korzystają z 2 wywołań dostępu do dokumentu w celu sprawdzenia każdego zapisu. W tym przypadku każdy zapis wykorzystuje 2 z 10 wywołań dostępu, a zbiorcze żądanie zapisu wykorzystuje 6 z 20 wywołań dostępu.

Przekroczenie któregokolwiek z limitów powoduje błąd odmowy uprawnień.

Niektóre wywołania dostępu do dokumentów mogą być buforowane, a wywołania buforowane nie wliczają się do limitów.

Maksymalna głębokość zagnieżdżonej instrukcji match 10
Maksymalna długość ścieżki w segmentach ścieżki dozwolona w zestawie zagnieżdżonych instrukcji match 100
Maksymalna liczba zmiennych przechwytujących ścieżkę dozwolona w zestawie zagnieżdżonych instrukcji match 20
Maksymalna głębokość wywołania funkcji 20
Maksymalna liczba argumentów funkcji 7
Maksymalna liczba powiązań zmiennych let na funkcję 10
Maksymalna liczba wywołań funkcji rekurencyjnych lub cyklicznych 0 (niedozwolone)
Maksymalna liczba wyrażeń ocenianych na żądanie 1000
Maksymalny rozmiar zestawu reguł Zestawy reguł muszą przestrzegać dwóch ograniczeń rozmiaru:
  • limit 256 KB rozmiaru źródła tekstu zestawu reguł publikowanego z konsoli Firebase lub z interfejsu CLI przy użyciu firebase deploy .
  • limit 250 KB rozmiaru skompilowanego zestawu reguł, który powstaje, gdy Firebase przetwarza źródło i aktywuje je na zapleczu.

Następne kroki