Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

Warunki pisania reguł bezpieczeństwa Cloud Firestore

Podręcznik ten opiera się na strukturę zasad bezpieczeństwa , aby pokazać, jak dodać do swoich warunków chmurze FireStore zasad bezpieczeństwa przewodnika. 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 to wyrażenie logiczne, 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żytkowników, weryfikują przychodzące dane, a nawet uzyskują dostęp do innych części bazy danych.

Uwierzytelnianie

Jednym z najczęstszych wzorców reguł bezpieczeństwa jest kontrolowanie dostępu na podstawie stanu uwierzytelniania użytkownika. Na przykład Twoja aplikacja może chcieć zezwalać tylko zalogowanym użytkownikom na zapisywanie 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 powszechnym wzorcem jest upewnienie się, że użytkownicy mogą tylko odczytywać i zapisywać 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 aplikacja korzysta z uwierzytelniania Firebase lub Google Cloud Identity Platformę The request.auth zmienna zawiera informacje uwierzytelniania klienta wzywającej dane. Aby uzyskać więcej informacji na temat request.auth , zobacz dokumentację referencyjną .

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

resource zmienna odnosi się do żądanego dokumentu i resource.data jest mapa wszystkich pól i wartości zapisanych w dokumencie. Aby uzyskać więcej informacji na temat resource zmiennej, zobacz dokumentację referencyjną .

Podczas zapisywania danych możesz chcieć porównać dane przychodzące z istniejącymi danymi. W tym przypadku, jeśli zestaw reguł pozwala na zapis w toku, request.resource zmienna zawiera stan przyszłego dokumentu. Do update operacji, które modyfikują tylko podzbiór pól dokumentu, request.resource zmienna będzie zawierać oczekującą stan dokumentu po operacji. Można sprawdzić wartości pól w request.resource aby zapobiec niepożądanym lub niespójne aktualizacje 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

Korzystanie z get() i exists() funkcje, swoje zasady bezpieczeństwa mogą oceniać przychodzące żądania wobec innych dokumentów znajdujących się w bazie danych. get() i exists() funkcjonuje zarówno spodziewać w pełni określone ścieżki dokumentów. Kiedy za pomocą zmiennych do ścieżek konstrukt do get() i exists() , trzeba wyraźnie uciec za pomocą zmiennych $(variable) składni.

W poniższym przykładzie, database zmienna zostaje schwytany przez mecz oświadczenie match /databases/{database}/documents i wykorzystywane do tworzenia ś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
    }
  }
}

Do zapisu, można użyć getAfter() funkcji, aby uzyskać dostęp do stanu dokumentu po transakcji lub partii pisze uzupełnia ale przed transakcją lub wsadowych zobowiązuje. Jak get() The getAfter() funkcja przyjmuje w pełni określoną ścieżkę dokumentu. Można użyć getAfter() , aby zdefiniować zestawy pisze, że musi odbywać się wspólnie jako transakcję lub partii.

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

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

  • 10 dla żądań pojedynczych dokumentów i zapytań.
  • 20 dla odczytów wielu dokumentów, transakcji i zapisów wsadowych. Poprzedni limit 10 dotyczy również każdej operacji.

    Na przykład wyobraź sobie, że tworzysz grupowe żądanie zapisu z 3 operacjami zapisu, a Twoje reguły zabezpieczeń używają 2 wywołań dostępu do dokumentów do sprawdzania poprawności każdego zapisu. W tym przypadku każdy zapis wykorzystuje 2 z 10 wywołań dostępu, a grupowe żądanie zapisu wykorzystuje 6 z 20 wywołań dostępu.

Przekroczenie któregokolwiek z limitów skutkuje błędem odmowy uprawnień. Niektóre wywołania dostępu do dokumentów mogą być buforowane, a wywołania buforowane nie wliczają się do limitów.

Dla szczegółowego wyjaśnienia, jak te ograniczenia wpływają transakcje i batched pisze zobacz przewodnik dla zabezpieczania operacji atomowych .

Dostęp do połączeń i cen

Użycie tych funkcji powoduje wykonanie operacji odczytu w Twojej bazie danych, co oznacza, że ​​zostaniesz obciążony opłatą za odczytanie dokumentów, nawet jeśli Twoje reguły odrzucą żądanie. Zobacz Ceny Chmura FireStore bardziej konkretnych informacji rozliczeniowych.

Funkcje niestandardowe

W miarę jak twoje reguły bezpieczeństwa stają się coraz bardziej złożone, możesz chcieć otoczyć zestawy warunków funkcjami, które możesz ponownie wykorzystać w swoim 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 jeden return oświadczenie. 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 są zdefiniowane. Na przykład, funkcja zdefiniowana w service cloud.firestore zakresie ma dostęp do resource zmiennej i wbudowane funkcje, takie jak get() i exists() .
  • Funkcje mogą wywoływać inne funkcje, ale nie mogą rekursywnie. Całkowita głębokość stosu wywołań jest ograniczona do 10.
  • W wersji zasady v2 , funkcje można zdefiniować zmienne za pomocą let słowa kluczowego. Funkcje mogą mieć do 10 powiązań let, ale muszą kończyć się instrukcją return.

Funkcja jest zdefiniowana z function hasła i bierze zero lub więcej argumentów. Na przykład możesz chcieć połączyć dwa typy warunków użyte 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();
    }
  }
}

Używanie funkcji w regułach bezpieczeństwa sprawia, że ​​są one łatwiejsze do utrzymania w miarę wzrostu złożoności reguł.

Reguły to nie filtry

Gdy zabezpieczysz swoje dane i zaczniesz pisać zapytania, 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 bieżący klient ma uprawnienia dostępu.

Weźmy na przykład 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: Zasada ta odrzuca następujące zapytanie, ponieważ zestaw wyników może zawierać 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: Zasada ta pozwala na następujące zapytanie, ponieważ where("visibility", "==", "public") gwarantuje, że klauzula zestaw wyników spełnia warunek Zasadą jest:

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 odrzuca żądanie, jeśli może zwrócić dokument, do którego odczytanie klient nie ma uprawnień. Zapytania muszą być zgodne z ograniczeniami określonymi przez reguły bezpieczeństwa. Więcej informacji na temat zasad bezpieczeństwa i zapytań, patrz bezpiecznie pobierania danych .

Następne kroki