Tworzenie struktury reguł zabezpieczeń Cloud Firestore

Reguły zabezpieczeń Cloud Firestore pozwalają kontrolować dostęp 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 do całej bazy danych po operacje na określonym dokumencie.

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

Deklaracja dotycząca usługi i bazy danych

Reguły zabezpieczeń Cloud Firestore zawsze zaczynają się od tej deklaracji:

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

Deklaracja service cloud.firestore ogranicza reguły do Cloud Firestore, co zapobiega konfliktom między regułami zabezpieczeń Cloud Firestore a regułami 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 1 bazę danych o nazwie (default).

Podstawowe reguły odczytu/zapisu

Reguły podstawowe składają się z instrukcji match określającej ścieżkę dokumentu i wyrażenia allow ze szczegółowymi informacjami o tym, że odczyt określonych danych jest dozwolony:

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ć dokumenty, a nie kolekcje. Instrukcja dopasowania może wskazywać konkretny dokument, np. match /cities/SF, lub używać symboli wieloznacznych do wskazywania dowolnego dokumentu w danej ścieżce, np. match /cities/{city}.

W przykładzie powyżej instrukcja dopasowania używa składni z symbolem wieloznacznym {city}. Oznacza to, że reguła ma zastosowanie do wszystkich dokumentów w kolekcji cities, np. /cities/SF czy /cities/NYC. Podczas oceniania wyrażeń allow w instrukcjach dopasowania zmienna city zwróci nazwę dokumentu miasta, np. SF lub NYC.

Operacje szczegółowe

W niektórych sytuacjach dobrze jest podzielić read i write na bardziej szczegółowe operacje. Na przykład aplikacja może wymuszać inne warunki przy tworzeniu dokumentów niż przy usuwaniu dokumentów. Możesz też zezwolić na odczyt pojedynczego dokumentu, ale odrzucać duże zapytania.

Reguły 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 kolekcje 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.

Weź pod uwagę sytuację, w której każdy dokument w kolekcji cities zawiera kolekcję podrzędną landmarks. Reguły zabezpieczeń są stosowane tylko w przypadku dopasowanej ścieżki, więc ustawienia dostępu zdefiniowane w kolekcji cities nie mają zastosowania do podkolekcji landmarks. Zamiast tego utwórz jawne reguły, aby kontrolować 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>;
        }
    }
  }
}

Gdy zagnieżdżasz instrukcje match, ścieżka wewnętrznej instrukcji match jest zawsze określana względem ścieżki zewnętrznej instrukcji match. Te zestawy reguł są więc 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 były stosowane do dowolnej głębokiej hierarchii, użyj rekurencyjnej składni z symbolami wieloznacznymi ({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>;
    }
  }
}

Jeśli używasz składni rekurencyjnego symbolu wieloznacznego, zmienna z symbolem wieloznacznym 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. Wymienione powyżej reguły będą na przykład pasować do dokumentu znajdującego się pod adresem /cities/SF/landmarks/coit_tower, a wartość zmiennej document będzie wynosić SF/landmarks/coit_tower.

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

Wersja 1

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

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

Wersja 2

W wersji 2 reguł zabezpieczeń rekurencyjne symbole wieloznaczne pasują do 0 lub więcej elementów ścieżki. match/cities/{city}/{document=**} dopasowuje dokumenty ze wszystkich podkolekcji oraz dokumenty z kolekcji cities.

Musisz zaakceptować wersję 2, dodając rules_version = '2'; u góry 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 każdej instrukcji dopasowania można użyć maksymalnie 1 rekurencyjnego symbolu wieloznacznego, ale w wersji 2 możesz go umieścić w dowolnym miejscu w instrukcji 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 korzystasz z zapytań dotyczących grup kolekcji, musisz używać wersji 2. Więcej informacji o zabezpieczaniu zapytań dotyczących grup kolekcji.

Nakładające się instrukcje dopasowania

Dokument może pasować do więcej niż jednej instrukcji match. W przypadku gdy do żądania pasuje wiele wyrażeń allow, dostęp jest dozwolony, jeśli którykolwiek z warunków jest zgodny z 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 odczyty i zapisy w kolekcji cities są dozwolone, ponieważ druga reguła to zawsze true, choć pierwsza to zawsze false.

Limity reguł zabezpieczeń

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

Limit Szczegóły
Maksymalna liczba wywołań exists(), get() i getAfter() na żądanie
  • 10 w przypadku żądań pojedynczych dokumentów i zapytań.
  • 20 – odczyty, transakcje i zapisy wsadowe w wielu dokumentach. Do każdej operacji ma też zastosowanie poprzedni limit 10.

    Załóżmy na przykład, że tworzysz wsadowe żądanie zapisu z 3 operacjami zapisu i że Twoje reguły zabezpieczeń używają 2 wywołań dostępu do dokumentu do weryfikacji każdego zapisu. W tym przypadku każdy zapis używa 2 z 10 wywołań dostępu, a wsadowe żądanie zapisu używa 6 z 20 wywołań dostępu.

Przekroczenie dowolnego z limitów skutkuje błędem 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żonej instrukcji match 10
Maksymalna długość ścieżki w segmentach ścieżki dozwolona w zbiorze zagnieżdżonych instrukcji match 100
Maksymalna liczba zmiennych przechwytywania ścieżki 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 na funkcję (let) 10
Maksymalna liczba rekurencyjnych lub cyklicznych wywołań funkcji 0 &lpar;niedozwolone&rpar;
Maksymalna liczba wyrażeń ocenianych na żądanie 1000
Maksymalny rozmiar zestawu reguł Zestawy reguł muszą przestrzegać 2 limitów rozmiarów:
  • Limit 256 KB dotyczący rozmiaru źródła tekstu zbioru reguł opublikowanego z poziomu konsoli Firebase lub z poziomu interfejsu wiersza poleceń za pomocą interfejsu firebase deploy.
  • Limit 250 KB odnoszący się do skompilowanego zestawu reguł, który pojawia się, gdy Firebase przetworzy źródło i aktywuje je w backendzie.

Dalsze kroki