Google is committed to advancing racial equity for Black communities. See how.
Ta strona została przetłumaczona przez Cloud Translation API.
Switch to English

Warunki pisania dla reguł zabezpieczeń Cloud Firestore

Ten przewodnik opiera się na przewodniku dotyczącym strukturyzowania reguł bezpieczeństwa i pokazuje, jak dodawać warunki do reguł zabezpieczeń Cloud Firestore. Jeśli nie są zaznajomieni z podstawami cloud FireStore zasad bezpieczeństwa można znaleźć w podręcznej instrukcji.

Podstawowym elementem składowym reguł zabezpieczeń Cloud Firestore jest warunek. Warunek jest wyrażeniem logicznym, które określa, czy dana operacja powinna być dozwolona, ​​czy zabroniona. Użyj reguł bezpieczeństwa, aby napisać warunki, które sprawdzają uwierzytelnianie użytkownika, weryfikują przychodzące dane, a nawet uzyskują dostęp do innych części bazy danych.

Poświadczenie

Jednym z najpowszechniejszych wzorców reguł bezpieczeństwa jest kontrolowanie dostępu na podstawie stanu uwierzytelnienia użytkownika. Na przykład Twoja aplikacja może chcieć zezwalać tylko zalogowanym użytkownikom na zapis 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 upewnienie się, że użytkownicy mogą odczytywać i zapisywać tylko własne 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, zmienna request.auth zawiera informacje uwierzytelniające dla klienta żądającego danych. Więcej informacji na temat request.auth można znaleźć w dokumentacji referencyjnej .

Walidacji danych

Wiele aplikacji przechowuje informacje o kontroli dostępu jako pola w dokumentach w bazie danych. Reguły zabezpieczeń Cloud Firestore mogą dynamicznie zezwalać lub odmawiać dostępu na podstawie danych dokumentu:

 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 mapa wszystkich pól i wartości przechowywanych w dokumencie. Więcej informacji na temat zmiennej resource można znaleźć w dokumentacji referencyjnej .

Podczas zapisywania danych możesz chcieć porównać przychodzące dane z istniejącymi danymi. W tym przypadku, jeśli zestaw reguł zezwala na oczekujący zapis, zmienna request.resource zawiera przyszły stan dokumentu. W przypadku operacji update , które modyfikują tylko podzbiór pól dokumentu, zmienna request.resource będzie zawierać stan dokumentu oczekującego po operacji. Możesz sprawdzić wartości pól w request.resource aby zapobiec niechcianym 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;
    }
  }
}
 

Uzyskaj dostęp do innych dokumentów

Korzystając z funkcji get() i exists() , reguły bezpieczeństwa mogą oceniać przychodzące żądania względem innych dokumentów w bazie danych. Funkcje get() i exists() oczekują w pełni określonych ścieżek dokumentów. Używając zmiennych do konstruowania ścieżek dla funkcji get() i exists() , należy jawnie zmieniać znaczenie zmiennych przy użyciu składni $(variable) .

W poniższym przykładzie zmienna database jest przechwytywana przez instrukcję 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żna użyć funkcji getAfter() aby uzyskać dostęp do stanu dokumentu po zakończeniu transakcji lub partii zapisów, ale przed zatwierdzeniem transakcji lub partii. Podobnie jak get() , funkcja getAfter() przyjmuje w pełni określoną ścieżkę do dokumentu. Możesz użyć getAfter() do zdefiniowania zestawów zapisów, które muszą mieć miejsce razem jako transakcja lub partia.

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

Istnieje limit wywołań dostępu do dokumentów na ocenę zestawu reguł:

  • 10 dla wniosków o pojedyncze dokumenty i zapytań.
  • 20 dla odczytów wielu dokumentów, transakcji i zapisów wsadowych. Poprzedni limit 10 ma również zastosowanie do każdej operacji.

    Na przykład wyobraź sobie, że tworzysz wsadowe żądanie zapisu z 3 operacjami zapisu i że Twoje reguły bezpieczeństwa używają 2 wywołań dostępu do dokumentów w celu sprawdzenia każdego zapisu. W tym przypadku każdy zapis wykorzystuje 2 z 10 wywołań dostępu, a wsadowe żą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 te z pamięci podręcznej nie wliczają się do limitów.

Aby uzyskać szczegółowe wyjaśnienie, jak te limity wpływają na transakcje i zapisy wsadowe, zobacz przewodnik dotyczący zabezpieczania operacji atomowych .

Dostęp do połączeń i cen

Korzystanie z tych funkcji powoduje wykonanie operacji odczytu w bazie danych, co oznacza, że ​​zostaniesz obciążony opłatą za odczyt dokumentów, nawet jeśli Twoje reguły odrzucą żądanie. Bardziej szczegółowe informacje rozliczeniowe można znaleźć w cenniku Cloud Firestore .

Funkcje niestandardowe

Ponieważ reguły bezpieczeństwa stają się bardziej złożone, możesz chcieć zawinąć zestawy warunków w funkcje, których możesz ponownie użyć 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 są napisane w języku specyficznym dla domeny, który ma kilka ważnych ograniczeń:

  • 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 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ć. Całkowita głębokość stosu wywołań jest ograniczona do 10.
  • W wersji v2 reguł funkcje mogą definiować zmienne za pomocą słowa kluczowego let . Funkcje mogą mieć maksymalnie 10 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. Na przykład możesz chcieć połączyć dwa typy warunków użytych 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 konserwację wraz ze wzrostem złożoności reguł.

Reguły nie są filtrami

Po zabezpieczeniu danych i rozpoczęciu pisania zapytań pamiętaj, że reguły bezpieczeństwa nie są filtrami. Nie możesz napisać zapytania dla wszystkich dokumentów w kolekcji i oczekiwać, że Cloud Firestore zwróci tylko te dokumenty, do których dostęp ma bieżący klient.

Na przykład weźmy następującą regułę bezpieczeństwa:

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

Odmowa : ta reguła odrzuca następujące zapytanie, ponieważ zestaw wyników może zawierać dokumenty, 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 następujące zapytanie, ponieważ klauzula where("visibility", "==", "public") gwarantuje, że zestaw 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 bezpieczeństwa Cloud Firestore oceniają każde zapytanie pod kątem jego potencjalnego wyniku i odrzucają żądanie, jeśli może ono zwrócić dokument, do którego odczytania klient nie ma uprawnień. Zapytania muszą być zgodne z ograniczeniami określonymi przez reguły zabezpieczeń. Aby uzyskać więcej informacji na temat reguł bezpieczeństwa i zapytań, zobacz bezpieczne tworzenie zapytań dotyczących danych .

Następne kroki