Tworzenie struktury reguł zabezpieczeń Cloud Firestore

Cloud Firestore Security Rules umożliwiają kontrolowanie dostępu do dokumentów i kolekcji w bazie danych. Elastyczna składnia reguł umożliwia tworzenie reguł, które pasują do wszystkiego, od wszystkich zapisów w całej bazie danych po operacje na konkretnym dokumencie.

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

Deklaracja dotycząca usługi i bazy danych

Cloud Firestore Security Rules zawsze zaczyna się od tego oświadczenia:

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

Deklaracja service cloud.firestore ogranicza zakres reguł do Cloud Firestore, zapobiegając konfliktom między Cloud Firestore Security Rules a regułami dotyczącymi innych usług, 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 reguły odczytu i zapisu

Podstawowe reguły składają się z oświadczenia match określającego ścieżkę dokumentu oraz wyrażenia allow określającego, kiedy jest dozwolone 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 oświadczenia o dopasowaniu powinny wskazywać dokumenty, a nie kolekcje. Instrukcja dopasowania może wskazywać konkretny dokument, jak w przypadku match /cities/SF, lub używać symboli wieloznacznych, aby wskazywać dowolny dokument na określonej ścieżce, jak w przypadku match /cities/{city}.

W powyższym przykładzie instrukcja dopasowania używa składni zastępnika {city}. Oznacza to, że reguła dotyczy każdego dokumentu w kolekcji cities, np. /cities/SF lub /cities/NYC. Gdy wyrażenia allow w oświadczeniu o dopasowaniu zostaną ocenione, zmienna city zostanie zastąpiona nazwą dokumentu miasta, np. SF lub NYC.

Operacje szczegółowe

W niektórych sytuacjach warto podzielić operacje readwrite na bardziej szczegółowe operacje. Aplikacja może na przykład wymagać spełnienia różnych warunków podczas tworzenia dokumentu i jego usuwania. Możesz też zezwolić na odczyt pojedynczego dokumentu, ale odrzucić duże zapytania.

Regułę read można podzielić na get i list, a regułę write 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ą porządkowane w kolekcji dokumentów, a każdy dokument może rozszerzać hierarchię za pomocą podkolekcji. Ważne jest, aby zrozumieć, jak reguły zabezpieczeń współdziałają z danymi hierarchicznymi.

Wyobraź sobie sytuację, w której każdy dokument w kolekcji cities zawiera podkolekcję landmarks. Reguły bezpieczeństwa mają zastosowanie tylko w przypadku dopasowanej ścieżki, więc mechanizmy kontroli dostępu zdefiniowane w zbiorze cities nie mają zastosowania do podzbioru landmarks. Zamiast tego napisz wyraźne reguły, które będą kontrolować dostęp do podzbiorów:

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

Gdy zagnieżdżasz instrukcje match, ścieżka wewnętrznej instrukcji match jest zawsze względna względem ścieżki zewnętrznej instrukcji match. Dlatego te 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>;
    }
  }
}

Symbole wieloznaczne rekurencyjne

Jeśli chcesz, aby reguły były stosowane w dowolnie głębokiej hierarchii, użyj rekurencyjnej składni z symbolem wieloznacznym {name=**}. 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>;
    }
  }
}

Gdy używasz rekurencyjnej składni symboli wieloznacznych, zmienna symbolu wieloznacznego zawiera cały pasujący segment ścieżki, nawet jeśli dokument znajduje się w głęboko zagnieżdżonym podzbiorze. Na przykład reguły wymienione powyżej pasują do dokumentu znajdującego się w folderze /cities/SF/landmarks/coit_tower, a wartość zmiennej document to SF/landmarks/coit_tower.

Pamiętaj jednak, że działanie symboli wieloznacznych rekurencyjnych zależy od wersji reguł.

Wersja 1

Reguły zabezpieczeń domyślnie używają wersji 1. W wersji 1 rekurencyjne symbole wieloznaczne pasują do co najmniej 1 elementu ścieżki. Nie pasują do pustej ścieżki, więc match /cities/{city}/{document=**} pasuje do dokumentów w kolekcjach podrzędnych, ale nie w kolekcji cities, podczas gdy match /cities/{document=**} pasuje do dokumentów w kolekcji cities i kolekcjach podrzędnych.

Rekurencyjne symbole wieloznaczne muszą znajdować się na końcu oświadczenia o dopasowaniu.

Wersja 2

W wersji 2 reguł zabezpieczeń symbole wieloznaczne w regułach rekurencyjnych pasują do 0 lub więcej elementów ścieżki. match/cities/{city}/{document=**} pasuje do dokumentów w dowolnych podkolekcjach, a także do dokumentów w kolekcji cities.

Musisz wyrazić zgodę na wersję 2, dodając rules_version = '2'; na początku swoich reguł zabezpieczeń:

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

W przypadku każdego wyrażenia dopasowania możesz użyć maksymalnie 1 rekursywnego symbolu wieloznacznego, ale w wersji 2 możesz umieścić ten symbol w dowolnym miejscu wyrażenia dopasowania. 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ń dotyczących grup kolekcji, musisz używać wersji 2. Więcej informacji znajdziesz w sekcji Zabezpieczanie zapytań dotyczących grup kolekcji.

Zachodzące na siebie wyrażenia dopasowania

Dokument może pasować do więcej niż jednego oświadczenia match. Jeśli wiele wyrażeń allow pasuje do żądania, dostęp jest udzielany, jeśli co najmniej jedno z tych wyrażeń jest true:

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 operacje odczytu i zapisu do kolekcji cities będą dozwolone, ponieważ druga reguła jest zawsze true, mimo że pierwsza reguła jest zawsze false.

Ograniczenia reguł zabezpieczeń

Podczas pracy z regułami zabezpieczeń pamiętaj o tych ograniczeniach:

Limit Szczegóły
Maksymalna liczba wywołań funkcji exists(), get() i getAfter() na żądanie
  • 10 w przypadku żądań dotyczących pojedynczego dokumentu i zapytań.
  • 20 dla odczytu wielu dokumentów, transakcji i zapisów zbiorczych. Poprzedni limit 10 operacji obowiązuje również w przypadku każdej operacji.

    Załóżmy na przykład, że tworzysz zbiorczy żądanie zapisu z 3 operacjami zapisu i że Twoje reguły zabezpieczeń używają 2 wywołań dostępu do dokumentu, aby zweryfikować każdy zapis. W tym przypadku każde zapisywanie korzysta z 2 z 10 wywołań dostępu, a żądanie zbiorczego zapisywania korzysta z 6 z 20 wywołań dostępu.

Przekroczenie któregokolwiek z tych limitów powoduje błąd dotyczący braku uprawnień.

Niektóre wywołania dostępu do dokumentu mogą być przechowywane w pamięci podręcznej, a wywołania z pamięci podręcznej nie wliczają się do limitów.

Maksymalna głębokość zagnieżdżonego wyrażenia match 10
Maksymalna długość ścieżki (w segmentach ścieżki) dozwolona w zbiorze ujęć match 100
Maksymalna liczba zmiennych przechwytywania ścieżki dozwolonych w zestawie ujętych w nawiasy match instrukcji 20
Maksymalna głębokość wywołania funkcji 20
Maksymalna liczba argumentów funkcji 7
Maksymalna liczba let powiązań zmiennych na funkcję 10
Maksymalna liczba rekurencyjnych lub cyklicznych wywołań funkcji 0 &lpar;niedozwolone&rpar;
Maksymalna liczba wyrażeń ocenianych na żądanie 1000
Maksymalny rozmiar zbioru reguł Reguły muszą spełniać 2 limity rozmiaru:
  • limit 256 KB na rozmiar źródła tekstowego reguł opublikowanego z poziomu konsoli Firebase lub za pomocą interfejsu wiersza poleceń za pomocą polecenia firebase deploy.
  • limit 250 KB na rozmiar skompilowanego zbioru reguł, który powstaje, gdy Firebase przetworzy źródło i uaktywni je na zapleczu;

Dalsze kroki