Warunki zapisu reguł zabezpieczeń Cloud Firestore

Ten przewodnik wykorzystuje informacje na temat tworzenia struktury reguł zabezpieczeń. aby pokazać, jak dodać warunki do reguł zabezpieczeń Cloud Firestore. Jeśli nie jesteś Zapoznaj się z podstawami reguł zabezpieczeń Cloud Firestore, zobacz wprowadzenie Google.

Podstawowym elementem składowym reguł zabezpieczeń Cloud Firestore jest warunek. O Warunek jest wyrażeniem logicznym określającym, czy określona operacja powinno być dozwolone lub zabronione. Użyj reguł zabezpieczeń do zapisania warunków, które sprawdzania uwierzytelniania użytkowników, weryfikowania przychodzących danych, a nawet uzyskiwania dostępu do innych części w bazie danych.

Uwierzytelnianie

Jednym z najczęstszych wzorców reguł zabezpieczeń jest kontrola dostępu stan uwierzytelniania użytkownika. Na przykład aplikacja może zezwalać tylko na zalogowanych użytkowników w celu zapisywania danych:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth != null;
    }
  }
}

Innym częstym wzorcem jest zapewnienie użytkownikom możliwości odczytu i zapisu tylko własnych dane:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null;
    }
  }
}

Jeśli Twoja aplikacja korzysta z uwierzytelniania Firebase lub z Google Cloud Identity Platform, zmienna request.auth zawiera dane uwierzytelniające klienta, który żąda danych. Więcej informacji o request.auth znajdziesz w dokumentacji dokumentacji.

Walidacja danych

Wiele aplikacji przechowuje informacje o kontroli dostępu jako pola dokumentów w bazie danych. Reguły zabezpieczeń Cloud Firestore mogą dynamicznie przyznawać i blokować dostęp na podstawie dokumentu dane:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

Zmienna resource odnosi się do żądanego dokumentu, a resource.data to mapę wszystkich pól i wartości przechowywanych w dokumencie. Więcej informacji o zmiennej resource znajdziesz w dokumentacji dokumentacji.

Podczas zapisywania danych możesz chcieć porównać dane przychodzące z danymi istniejącymi. W tym przypadku, jeśli Twój zbiór reguł zezwala na oczekujący zapis, request.resource zawiera przyszły stan dokumentu. W przypadku operacji update, które mają tylko jeśli zmodyfikujesz podzbiór pól dokumentu, zmienna request.resource będzie zawierają stan dokumentu oczekującego po zakończeniu operacji. Możesz zaznaczyć to pole, wartości w polu request.resource, aby zapobiec niepożądanym lub niespójnym aktualizacjom danych:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}

Dostęp do innych dokumentów

Za pomocą funkcji get() i exists() reguły zabezpieczeń mogą oceniać żądań przychodzących do innych dokumentów w bazie danych. get() i Obie funkcje exists() oczekują w pełni określonych ścieżek dokumentów. W przypadku użycia funkcji do tworzenia ścieżek dla get() i exists(), musisz wyraźnie wskazać zmiennych ucieczki, używając składni $(variable).

W poniższym przykładzie zmienna database jest rejestrowana przez dopasowanie instrukcja match /databases/{database}/documents i używana do utworzenia ścieżki:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid));

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
    }
  }
}

W przypadku zapisów możesz użyć funkcji getAfter(), aby uzyskać dostęp do stanu po zakończeniu transakcji lub partii zapisów, ale przed zatwierdzeń transakcyjnych lub wsadowych. Podobnie jak get(), funkcja getAfter() przyjmuje w pełni określoną ścieżkę dokumentu. Do definiowania zbiorów zapisów możesz użyć parametru getAfter() które muszą zostać zrealizowane łącznie jako transakcja lub wsad.

Dostęp do limitów połączeń

Obowiązuje limit wywołań dostępu do dokumentu na ocenę zestawu reguł:

  • 10 w przypadku żądań pojedynczych dokumentów i zapytań.
  • 20 w przypadku odczytów wielu dokumentów, transakcji, i zapisy wsadowe. Poprzedni limit 10 obowiązuje również w przypadku .

    Wyobraź sobie na przykład, że tworzysz wsadowe żądanie zapisu z 3 zapisami oraz aby reguły zabezpieczeń używały 2 wywołań dostępu do dokumentu i weryfikować każdy zapis. W tym przypadku każdy zapis używa 2 ze swoich 10 wywołań dostępu, a grupowe żądanie zapisu korzysta z 6 z 20 połączeń.

Przekroczenie dowolnego z limitów skutkuje błędem braku uprawnień. Jakiś dokument Połączenia w trybie dostępu mogą być przechowywane w pamięci podręcznej, a połączenia z tej pamięci nie wliczają się do limitów.

Aby uzyskać szczegółowe informacje o tym, jak te limity wpływają na transakcje zapisy wsadowe – zobacz przewodnik na temat zabezpieczania operacji niepodzielnych.

Dostęp do połączeń i cen

Użycie tych funkcji pozwala wykonać operację odczytu w bazie danych, co oznacza, że opłata za czytanie dokumentów jest naliczana nawet wtedy, gdy reguły zostaną odrzucone. do ich przesłania. Zobacz cennik Cloud Firestore bardziej szczegółowe informacje rozliczeniowe.

Funkcje niestandardowe

W miarę jak Twoje reguły zabezpieczeń stają się bardziej złożone, być może warto opakować zestawy warunków w funkcjach, których możesz używać ponownie w zestawie reguł. Reguły zabezpieczeń i obsługują funkcje niestandardowe. Składnia funkcji niestandardowych jest podobna do JavaScriptu, ale funkcje reguł zabezpieczeń są napisane w języku specyficznym dla danej domeny, który ma kilka ważnych ograniczeń:

  • Funkcje mogą zawierać tylko jedną instrukcję return. Nie mogą nie zawierają żadnych dodatkowych elementów logicznych. Nie mogą na przykład wykonywać pętli ani wywołań i usług zewnętrznych.
  • Funkcje mogą automatycznie uzyskiwać dostęp do funkcji i zmiennych z zakresu w których są zdefiniowane. Na przykład funkcja zdefiniowana w argumencie zakres service cloud.firestore ma dostęp do zmiennej resource i wbudowanych funkcji, takich jak get() i exists().
  • Funkcje mogą wywoływać inne funkcje, ale nie mogą się powtarzać. Łączna liczba połączeń głębokość stosu jest ograniczona do 10.
  • W regułach w wersji v2 funkcje mogą definiować zmienne za pomocą słowa kluczowego let. Funkcje mogą mieć do 10 powiązań zezwalających, ale muszą kończyć się zwrotem .

Funkcja jest zdefiniowana za pomocą słowa kluczowego function i przyjmuje zero lub więcej wartości. . Możesz na przykład połączyć 2 rodzaje warunków, których używa się w powyższych przykładach w jedną funkcję:

service cloud.firestore {
  match /databases/{database}/documents {
    // 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 /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

Korzystanie z funkcji w regułach zabezpieczeń ułatwia ich obsługę, tym większa złożoność reguł.

Reguły nie są filtrami

Gdy zabezpieczysz dane i zaczniesz pisać zapytania, pamiętaj, że funkcje zabezpieczeń Reguły nie są filtrami. Nie można utworzyć zapytania dotyczącego wszystkich dokumentów w i oczekiwanie, że Cloud Firestore zwróci tylko dokumenty, bieżący klient ma uprawnienia dostępu.

Na przykład taka reguła zabezpieczeń:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

Odrzucono: ta reguła odrzuca następujące zapytanie, ponieważ ustawiono wynik mogą obejmować dokumenty, w których visibility nie jest public:

Sieć
db.collection("cities").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
    });
});

Dozwolone: ta reguła zezwala na poniższe zapytanie, ponieważ klauzula where("visibility", "==", "public") gwarantuje, że zbiór wyników spełnia warunek reguły:

Sieć
db.collection("cities").where("visibility", "==", "public").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
        });
    });

Reguły zabezpieczeń Cloud Firestore oceniają każde zapytanie pod kątem jego potencjału i nie powiedzie się, jeśli może zwrócić dokument wykonany przez klienta nie mają uprawnień do odczytu. Zapytania muszą spełniać ograniczenia ustawione przez reguły zabezpieczeń. Więcej informacji o regułach i zapytaniach dotyczących bezpieczeństwa znajdziesz w artykule Bezpiecznie zapytań o dane.

Dalsze kroki