Reguły bezpieczeństwa Firebase wykorzystują elastyczne, wydajne, niestandardowe języki, które obsługują szeroki zakres złożoności i szczegółowości. Możesz ustawić reguły tak szczegółowe lub ogólne, jak ma to sens w przypadku Twojej aplikacji. Reguły bazy danych czasu rzeczywistego korzystają ze składni przypominającej JavaScript w strukturze JSON. Reguły Cloud Firestore i Cloud Storage używają języka opartego na Common Expression Language (CEL) , który opiera się na CEL z instrukcjami match
i allow
, które obsługują warunkowo przyznany dostęp.
Ponieważ są to języki niestandardowe, istnieje jednak krzywa uczenia się. Skorzystaj z tego przewodnika, aby lepiej zrozumieć język Reguł, zagłębiając się w bardziej złożone reguły.
Wybierz produkt, aby dowiedzieć się więcej o jego zasadach.
Podstawowa struktura
Chmura Firestore
Reguły bezpieczeństwa Firebase w Cloud Firestore i Cloud Storage korzystają z następującej struktury i składni:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
Podczas tworzenia reguł należy zrozumieć następujące kluczowe pojęcia:
- Żądanie: Metoda lub metody wywoływane w instrukcji
allow
. Są to metody, którym pozwalasz na uruchamianie. Standardowe metody to:get
,list
,create
,update
idelete
. Wygodne metodyread
iwrite
umożliwiają szeroki dostęp do odczytu i zapisu w określonej bazie danych lub ścieżce przechowywania. - Ścieżka: lokalizacja bazy danych lub przechowywania reprezentowana jako ścieżka URI.
- Reguła:
allow
zezwalająca zawierająca warunek zezwalający na żądanie, jeśli ma ono wartość true.
Każde z tych pojęć opisano bardziej szczegółowo poniżej.
Magazyn w chmurze
Reguły bezpieczeństwa Firebase w Cloud Firestore i Cloud Storage korzystają z następującej struktury i składni:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
Podczas tworzenia reguł należy zrozumieć następujące kluczowe pojęcia:
- Żądanie: Metoda lub metody wywoływane w instrukcji
allow
. Są to metody, którym pozwalasz na uruchamianie. Standardowe metody to:get
,list
,create
,update
idelete
. Wygodne metodyread
iwrite
umożliwiają szeroki dostęp do odczytu i zapisu w określonej bazie danych lub ścieżce przechowywania. - Ścieżka: lokalizacja bazy danych lub przechowywania reprezentowana jako ścieżka URI.
- Reguła:
allow
zezwalająca zawierająca warunek zezwalający na żądanie, jeśli ma ono wartość true.
Każde z tych pojęć opisano bardziej szczegółowo poniżej.
Baza danych czasu rzeczywistego
W bazie danych czasu rzeczywistego reguły bezpieczeństwa Firebase składają się z wyrażeń przypominających JavaScript zawartych w dokumencie JSON.
Używają następującej składni:
{
"rules": {
"<<path>>": {
// Allow the request if the condition for each method is true.
".read": <<condition>>,
".write": <<condition>>,
".validate": <<condition>>
}
}
}
Reguła składa się z trzech podstawowych elementów:
- Ścieżka: lokalizacja bazy danych. Odzwierciedla to strukturę JSON Twojej bazy danych.
- Żądanie: są to metody używane przez regułę do udzielania dostępu. Reguły
read
iwrite
zapewniają szeroki dostęp do odczytu i zapisu, natomiast regułyvalidate
działają jako dodatkowa weryfikacja w celu przyznania dostępu na podstawie przychodzących lub istniejących danych. - Warunek: Warunek, który zezwala na żądanie, jeśli ma wartość true.
Konstrukcje reguł
Chmura Firestore
Podstawowe elementy reguły w Cloud Firestore i Cloud Storage są następujące:
- Deklaracja
service
: deklaruje produkt Firebase, do którego mają zastosowanie reguły. - Blok
match
: definiuje ścieżkę w bazie danych lub zasobniku pamięci, do którego mają zastosowanie reguły. - Instrukcja
allow
: zapewnia warunki przyznawania dostępu, zróżnicowane według metod. Obsługiwane metody obejmują:get
,list
,create
,update
,delete
oraz wygodne metodyread
iwrite
. - Opcjonalne deklaracje
function
: zapewniają możliwość łączenia i zawijania warunków do użycia w wielu regułach.
service
zawiera jeden lub więcej bloków match
z allow
zezwalającymi, które zapewniają warunki przyznające dostęp do żądań. Zmienne request
i resource
są dostępne do użycia w warunkach reguły. Język Firebase Security Rules obsługuje również deklaracje function
.
Wersja składni
Instrukcja syntax
wskazuje wersję języka Firebase Rules użytego do napisania źródła. Najnowsza wersja języka to v2
.
rules_version = '2';
service cloud.firestore {
...
}
Jeśli nie zostanie podana instrukcja rules_version
, Twoje reguły zostaną ocenione przy użyciu silnika v1
.
Praca
Deklaracja service
określa, którego produktu lub usługi Firebase dotyczą Twoje reguły. Do każdego pliku źródłowego można dołączyć tylko jedną deklarację service
.
Chmura Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Magazyn w chmurze
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Jeśli definiujesz reguły zarówno dla Cloud Firestore, jak i Cloud Storage przy użyciu interfejsu CLI Firebase, będziesz musiał zachować je w oddzielnych plikach.
Mecz
Blok match
deklaruje wzorzec path
, który jest dopasowywany do ścieżki żądanej operacji (przychodzące request.path
). Treść match
musi zawierać co najmniej jeden zagnieżdżony blok match
, allow
lub deklaracje function
. Ścieżka w zagnieżdżonych blokach match
jest określana względem ścieżki w nadrzędnym bloku match
.
path
ścieżki to nazwa przypominająca katalog, która może zawierać zmienne lub symbole wieloznaczne. Wzorzec path
umożliwia dopasowanie segmentu jednościeżkowego i segmentu wielościeżkowego. Wszelkie zmienne powiązane ze path
są widoczne w zakresie match
lub w dowolnym zakresie zagnieżdżonym, w którym zadeklarowana jest path
.
Dopasowania do wzorca path
mogą być częściowe lub całkowite:
- Częściowe dopasowania: wzorzec
path
jest dopasowaniem przedrostkarequest.path
. - Kompletne dopasowania:
path
ścieżki pasuje do całegorequest.path
.
Po całkowitym dopasowaniu oceniane są reguły zawarte w bloku. Kiedy następuje częściowe dopasowanie, testowane są reguły match
zagnieżdżonego, aby sprawdzić, czy jakakolwiek zagnieżdżona path
zakończy dopasowanie.
Reguły w każdym pełnym match
są oceniane w celu ustalenia, czy zezwolić na żądanie. Jeśli jakakolwiek pasująca reguła zapewnia dostęp, żądanie jest dozwolone. Jeśli żadna pasująca reguła nie przyzna dostępu, żądanie zostanie odrzucone.
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
Jak pokazuje powyższy przykład, deklaracje path
obsługują następujące zmienne:
- Jednosegmentowy symbol wieloznaczny: Zmienna wieloznaczna jest deklarowana w ścieżce poprzez zawijanie zmiennej w nawiasy klamrowe:
{variable}
. Ta zmienna jest dostępna w instrukcjimatch
jakostring
. - Rekurencyjny symbol wieloznaczny: rekurencyjny lub wielosegmentowy symbol wieloznaczny dopasowuje wiele segmentów ścieżki na ścieżce lub pod nią. Ten symbol wieloznaczny pasuje do wszystkich ścieżek poniżej lokalizacji, w której go ustawiłeś. Możesz to zadeklarować, dodając ciąg
=**
na końcu zmiennej segmentu:{variable=**}
. Ta zmienna jest dostępna w instrukcjimatch
jako obiektpath
.
Umożliwić
Blok match
zawiera jedną lub więcej instrukcji allow
. To są Twoje aktualne zasady. Reguły allow
można zastosować do jednej lub większej liczby metod. Warunki w instrukcji allow
muszą mieć wartość true, aby Cloud Firestore lub Cloud Storage mogły spełnić każde przychodzące żądanie. Można także pisać allow
zezwalające bez warunków, na przykład allow read
. Jeśli jednak instrukcja allow
nie zawiera warunku, zawsze zezwala na żądanie tej metody.
Jeśli którakolwiek z reguł allow
dla metody jest spełniona, żądanie jest dozwolone. Ponadto, jeśli dostęp zapewnia szersza reguła, Reguły przyznają dostęp i ignorują bardziej szczegółowe reguły, które mogą ograniczać dostęp.
Rozważmy następujący przykład, w którym każdy użytkownik może czytać lub usuwać dowolne własne pliki. Bardziej szczegółowa reguła zezwala na zapis tylko wtedy, gdy użytkownik żądający zapisu jest właścicielem pliku, a plik jest w formacie PNG. Użytkownik może usunąć dowolne pliki ze ścieżki podrzędnej — nawet jeśli nie są to pliki PNG — ponieważ pozwala na to wcześniejsza reguła.
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
metoda
Każda instrukcja allow
zawiera metodę, która przyznaje dostęp żądaniom przychodzącym tej samej metody.
metoda | Typ prośby |
---|---|
Metody wygody | |
read | Dowolny rodzaj żądania odczytu |
write | Dowolny rodzaj żądania zapisu |
Metody standardowe | |
get | Czytaj prośby o pojedyncze dokumenty lub pliki |
list | Przeczytaj prośby o zapytania i kolekcje |
create | Napisz nowe dokumenty lub pliki |
update | Zapisz w istniejących dokumentach bazy danych lub zaktualizuj metadane pliku |
delete | Usunąć dane |
Nie można nakładać się metod odczytu w tym samym bloku match
ani kolidujących metod zapisu w tej samej deklaracji path
.
Na przykład następujące reguły nie powiodą się:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
Funkcjonować
W miarę jak reguły bezpieczeństwa stają się coraz bardziej złożone, możesz chcieć zawrzeć zestawy warunków w funkcjach, których będziesz mógł ponownie używać 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 zmiennejresource
i wbudowanych funkcji, takich jakget()
iexists()
. - Funkcje mogą wywoływać inne funkcje, ale nie mogą się powtarzać. Całkowita głębokość stosu wywołań jest ograniczona do 20.
- W wersji reguł
v2
funkcje mogą definiować zmienne za pomocą słowa kluczowegolet
. 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. Możesz na przykład 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();
}
}
}
Oto przykład pokazujący argumenty funkcji i przypisania let. Niech instrukcje przypisania muszą być oddzielone średnikami.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Zwróć uwagę, jak przypisanie isAdmin
wymusza przeszukiwanie kolekcji admins. Aby uzyskać leniwą ocenę bez konieczności niepotrzebnych przeglądów, skorzystaj z zwierającej natury &&
(AND) i ||
(OR) porównania, aby wywołać drugą funkcję tylko wtedy, gdy isAuthor
ma wartość true (w przypadku porównań &&
) lub fałsz (w przypadku porównań ||
).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
Używanie funkcji w regułach bezpieczeństwa sprawia, że są one łatwiejsze w utrzymaniu w miarę wzrostu złożoności reguł.
Magazyn w chmurze
Podstawowe elementy reguły w Cloud Firestore i Cloud Storage są następujące:
- Deklaracja
service
: deklaruje produkt Firebase, do którego mają zastosowanie reguły. - Blok
match
: definiuje ścieżkę w bazie danych lub zasobniku pamięci, do którego mają zastosowanie reguły. - Instrukcja
allow
: zapewnia warunki przyznawania dostępu, zróżnicowane według metod. Obsługiwane metody obejmują:get
,list
,create
,update
,delete
oraz wygodne metodyread
iwrite
. - Opcjonalne deklaracje
function
: zapewniają możliwość łączenia i zawijania warunków do użycia w wielu regułach.
service
zawiera jeden lub więcej bloków match
z allow
zezwalającymi, które zapewniają warunki przyznające dostęp do żądań. Zmienne request
i resource
są dostępne do użycia w warunkach reguły. Język Firebase Security Rules obsługuje również deklaracje function
.
Wersja składni
Instrukcja syntax
wskazuje wersję języka Firebase Rules użytego do napisania źródła. Najnowsza wersja języka to v2
.
rules_version = '2';
service cloud.firestore {
...
}
Jeśli nie zostanie podana instrukcja rules_version
, Twoje reguły zostaną ocenione przy użyciu silnika v1
.
Praca
Deklaracja service
określa, którego produktu lub usługi Firebase dotyczą Twoje reguły. Do każdego pliku źródłowego można dołączyć tylko jedną deklarację service
.
Chmura Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Magazyn w chmurze
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Jeśli definiujesz reguły zarówno dla Cloud Firestore, jak i Cloud Storage przy użyciu interfejsu CLI Firebase, będziesz musiał zachować je w oddzielnych plikach.
Mecz
Blok match
deklaruje wzorzec path
, który jest dopasowywany do ścieżki żądanej operacji (przychodzące request.path
). Treść match
musi zawierać co najmniej jeden zagnieżdżony blok match
, allow
lub deklaracje function
. Ścieżka w zagnieżdżonych blokach match
jest określana względem ścieżki w nadrzędnym bloku match
.
path
ścieżki to nazwa przypominająca katalog, która może zawierać zmienne lub symbole wieloznaczne. Wzorzec path
umożliwia dopasowanie segmentu jednościeżkowego i segmentu wielościeżkowego. Wszelkie zmienne powiązane ze path
są widoczne w zakresie match
lub w dowolnym zakresie zagnieżdżonym, w którym zadeklarowana jest path
.
Dopasowania do wzorca path
mogą być częściowe lub całkowite:
- Częściowe dopasowania: wzorzec
path
jest dopasowaniem przedrostkarequest.path
. - Kompletne dopasowania:
path
ścieżki pasuje do całegorequest.path
.
Po całkowitym dopasowaniu oceniane są reguły zawarte w bloku. Kiedy następuje częściowe dopasowanie, testowane są reguły match
zagnieżdżonego, aby sprawdzić, czy jakakolwiek zagnieżdżona path
zakończy dopasowanie.
Reguły w każdym pełnym match
są oceniane w celu ustalenia, czy zezwolić na żądanie. Jeśli jakakolwiek pasująca reguła zapewnia dostęp, żądanie jest dozwolone. Jeśli żadna pasująca reguła nie przyzna dostępu, żądanie zostanie odrzucone.
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
Jak pokazuje powyższy przykład, deklaracje path
obsługują następujące zmienne:
- Jednosegmentowy symbol wieloznaczny: Zmienna wieloznaczna jest deklarowana w ścieżce poprzez zawijanie zmiennej w nawiasy klamrowe:
{variable}
. Ta zmienna jest dostępna w instrukcjimatch
jakostring
. - Rekurencyjny symbol wieloznaczny: rekurencyjny lub wielosegmentowy symbol wieloznaczny dopasowuje wiele segmentów ścieżki na ścieżce lub pod nią. Ten symbol wieloznaczny pasuje do wszystkich ścieżek poniżej lokalizacji, w której go ustawiłeś. Możesz to zadeklarować, dodając ciąg
=**
na końcu zmiennej segmentu:{variable=**}
. Ta zmienna jest dostępna w instrukcjimatch
jako obiektpath
.
Umożliwić
Blok match
zawiera jedną lub więcej instrukcji allow
. To są Twoje aktualne zasady. Reguły allow
można zastosować do jednej lub większej liczby metod. Warunki w instrukcji allow
muszą mieć wartość true, aby Cloud Firestore lub Cloud Storage mogły spełnić każde przychodzące żądanie. Można także pisać allow
zezwalające bez warunków, na przykład allow read
. Jeśli jednak instrukcja allow
nie zawiera warunku, zawsze zezwala na żądanie tej metody.
Jeśli którakolwiek z reguł allow
dla metody jest spełniona, żądanie jest dozwolone. Ponadto, jeśli dostęp zapewnia szersza reguła, Reguły przyznają dostęp i ignorują bardziej szczegółowe reguły, które mogą ograniczać dostęp.
Rozważmy następujący przykład, w którym każdy użytkownik może czytać lub usuwać dowolne własne pliki. Bardziej szczegółowa reguła zezwala na zapis tylko wtedy, gdy użytkownik żądający zapisu jest właścicielem pliku, a plik jest w formacie PNG. Użytkownik może usunąć dowolne pliki ze ścieżki podrzędnej — nawet jeśli nie są to pliki PNG — ponieważ pozwala na to wcześniejsza reguła.
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
metoda
Każda instrukcja allow
zawiera metodę, która przyznaje dostęp żądaniom przychodzącym tej samej metody.
metoda | Typ prośby |
---|---|
Metody wygody | |
read | Dowolny rodzaj żądania odczytu |
write | Dowolny rodzaj żądania zapisu |
Metody standardowe | |
get | Czytaj prośby o pojedyncze dokumenty lub pliki |
list | Przeczytaj prośby o zapytania i kolekcje |
create | Napisz nowe dokumenty lub pliki |
update | Zapisz w istniejących dokumentach bazy danych lub zaktualizuj metadane pliku |
delete | Usunąć dane |
Nie można nakładać się metod odczytu w tym samym bloku match
ani kolidujących metod zapisu w tej samej deklaracji path
.
Na przykład następujące reguły nie powiodą się:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
Funkcjonować
W miarę jak reguły bezpieczeństwa stają się coraz bardziej złożone, możesz chcieć zawrzeć zestawy warunków w funkcjach, których będziesz mógł ponownie używać 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 zmiennejresource
i wbudowanych funkcji, takich jakget()
iexists()
. - Funkcje mogą wywoływać inne funkcje, ale nie mogą się powtarzać. Całkowita głębokość stosu wywołań jest ograniczona do 20.
- W wersji reguł
v2
funkcje mogą definiować zmienne za pomocą słowa kluczowegolet
. 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. Możesz na przykład 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();
}
}
}
Oto przykład pokazujący argumenty funkcji i przypisania let. Niech instrukcje przypisania muszą być oddzielone średnikami.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Zwróć uwagę, jak przypisanie isAdmin
wymusza przeszukiwanie kolekcji admins. Aby uzyskać leniwą ocenę bez konieczności niepotrzebnych przeglądów, skorzystaj z zwierającej natury &&
(AND) i ||
(OR) porównania, aby wywołać drugą funkcję tylko wtedy, gdy isAuthor
ma wartość true (w przypadku porównań &&
) lub fałsz (w przypadku porównań ||
).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
Używanie funkcji w regułach bezpieczeństwa sprawia, że są one łatwiejsze w utrzymaniu w miarę wzrostu złożoności reguł.
Baza danych czasu rzeczywistego
Jak opisano powyżej, Reguły bazy danych czasu rzeczywistego obejmują trzy podstawowe elementy: lokalizację bazy danych jako odbicie struktury JSON bazy danych, typ żądania i warunek przyznający dostęp.
Lokalizacja bazy danych
Struktura reguł powinna być zgodna ze strukturą danych przechowywanych w bazie danych. Na przykład w aplikacji do czatowania zawierającej listę wiadomości możesz mieć dane wyglądające tak:
{
"messages": {
"message0": {
"content": "Hello",
"timestamp": 1405704370369
},
"message1": {
"content": "Goodbye",
"timestamp": 1405704395231
},
...
}
}
Twoje reguły powinny odzwierciedlać tę strukturę. Na przykład:
{
"rules": {
"messages": {
"$message": {
// only messages from the last ten minutes can be read
".read": "data.child('timestamp').val() > (now - 600000)",
// new messages must have a string content and a number timestamp
".validate": "newData.hasChildren(['content', 'timestamp']) &&
newData.child('content').isString() &&
newData.child('timestamp').isNumber()"
}
}
}
}
Jak pokazuje powyższy przykład, reguły bazy danych czasu rzeczywistego obsługują zmienną $location
w celu dopasowania segmentów ścieżki. Użyj przedrostka $
przed segmentem ścieżki, aby dopasować regułę do wszystkich węzłów podrzędnych na ścieżce.
{
"rules": {
"rooms": {
// This rule applies to any child of /rooms/, the key for each room id
// is stored inside $room_id variable for reference
"$room_id": {
"topic": {
// The room's topic can be changed if the room id has "public" in it
".write": "$room_id.contains('public')"
}
}
}
}
}
Można także używać $variable
równolegle ze stałymi nazwami ścieżek.
{
"rules": {
"widget": {
// a widget can have a title or color attribute
"title": { ".validate": true },
"color": { ".validate": true },
// but no other child paths are allowed
// in this case, $other means any key excluding "title" and "color"
"$other": { ".validate": false }
}
}
}
metoda
W bazie danych czasu rzeczywistego istnieją trzy typy reguł. Dwa z tych typów reguł — read
i write
— mają zastosowanie do metody żądania przychodzącego. Reguła validate
wymusza struktury danych oraz sprawdza format i zawartość danych. Reguły uruchamiają reguły .validate
po sprawdzeniu, czy reguła .write
zapewnia dostęp.
Typy reguł | |
---|---|
.Czytać | Opisuje, czy i kiedy dane mogą być odczytywane przez użytkowników. |
.pisać | Opisuje, czy i kiedy można zapisywać dane. |
.uprawomocnić | Określa, jak będzie wyglądać poprawnie sformatowana wartość, czy ma atrybuty podrzędne i typ danych. |
Domyślnie, jeśli nie zezwala na to żadna reguła, dostęp do ścieżki jest zabroniony.
Warunki budowlane
Chmura Firestore
Warunek to wyrażenie logiczne określające, czy dana operacja powinna być dozwolona, czy zabroniona. Zmienne request
i resource
zapewniają kontekst dla tych warunków.
request
żądania
Zmienna request
zawiera następujące pola i odpowiadające im informacje:
request.auth
Token sieciowy JSON (JWT) zawierający dane uwierzytelniające z uwierzytelniania Firebase. token auth
zawiera zestaw standardowych oświadczeń i wszelkich niestandardowych oświadczeń, które tworzysz za pomocą uwierzytelniania Firebase. Dowiedz się więcej o regułach bezpieczeństwa i uwierzytelnianiu Firebase .
request.method
request.method
może być dowolną metodą standardową lub metodą niestandardową. Wygodne metody read
i write
istnieją również w celu uproszczenia zasad pisania, które mają zastosowanie odpowiednio do wszystkich standardowych metod tylko do odczytu lub wszystkich standardowych metod tylko do zapisu.
request.params
request.params
zawierają wszelkie dane niezwiązane konkretnie z request.resource
, które mogą być przydatne do oceny. W praktyce mapa ta powinna być pusta dla wszystkich metod standardowych i powinna zawierać dane niezasobowe dla metod niestandardowych. Usługi muszą uważać, aby nie zmienić nazwy ani nie zmodyfikować typu żadnego z kluczy i wartości prezentowanych jako parametry.
request.path
Ścieżka request.path
to ścieżka do resource
docelowego. Ścieżka jest zależna od usługi. Segmenty ścieżki zawierające znaki inne niż bezpieczne adresy URL, takie jak /
są kodowane w adresie URL.
resource
resource
to bieżąca wartość w usłudze reprezentowana jako mapa par klucz-wartość. Odwołanie resource
w ramach warunku spowoduje co najwyżej jeden odczyt wartości z usługi. To wyszukiwanie będzie wliczane do limitu zasobu związanego z usługą. W przypadku żądań get
resource
będzie wliczany do limitu tylko w przypadku odmowy.
Operatory i pierwszeństwo operatorów
Skorzystaj z poniższej tabeli jako odniesienia do operatorów i ich odpowiedniego pierwszeństwa w Regułach dotyczących Cloud Firestore i Cloud Storage.
Biorąc b
a
pole f
i indeks i
.
Operator | Opis | Łączność |
---|---|---|
a[i] a() af | Indeks, połączenie, dostęp do pola | od lewej do prawej | !a -a | Jednoargumentowa negacja | od prawej do lewej |
a/ba%ba*b | Operatory multiplikatywne | od lewej do prawej |
a+b ab | Operatory addytywne | od lewej do prawej |
a>ba>=ba | Operatorzy relacyjni | od lewej do prawej |
a in b | Istnienie na liście lub mapie | od lewej do prawej |
a is type | Porównanie typów, gdzie type może być bool, int, float, liczba, ciąg, lista, mapa, znacznik czasu, czas trwania, ścieżka lub latlng | od lewej do prawej |
a==ba!=b | Operatory porównania | od lewej do prawej | a && b | Warunkowe ORAZ | od lewej do prawej |
a || b | Warunkowe LUB | od lewej do prawej |
a ? true_value : false_value | Wyrażenie trójskładnikowe | od lewej do prawej |
Magazyn w chmurze
Warunek to wyrażenie logiczne określające, czy dana operacja powinna być dozwolona, czy zabroniona. Zmienne request
i resource
zapewniają kontekst dla tych warunków.
request
żądania
Zmienna request
zawiera następujące pola i odpowiadające im informacje:
request.auth
Token sieciowy JSON (JWT) zawierający dane uwierzytelniające z uwierzytelniania Firebase. token auth
zawiera zestaw standardowych oświadczeń i wszelkich niestandardowych oświadczeń, które tworzysz poprzez uwierzytelnianie Firebase. Dowiedz się więcej o regułach bezpieczeństwa i uwierzytelnianiu Firebase .
request.method
request.method
może być dowolną metodą standardową lub metodą niestandardową. Wygodne metody read
i write
istnieją również w celu uproszczenia zasad pisania, które mają zastosowanie odpowiednio do wszystkich standardowych metod tylko do odczytu lub wszystkich standardowych metod tylko do zapisu.
request.params
request.params
zawierają wszelkie dane niezwiązane konkretnie z request.resource
, które mogą być przydatne do oceny. W praktyce mapa ta powinna być pusta dla wszystkich metod standardowych i powinna zawierać dane niezasobowe dla metod niestandardowych. Usługi muszą uważać, aby nie zmienić nazwy ani nie zmodyfikować typu żadnego z kluczy i wartości prezentowanych jako parametry.
request.path
Ścieżka request.path
to ścieżka do resource
docelowego. Ścieżka jest zależna od usługi. Segmenty ścieżki zawierające znaki inne niż bezpieczne adresy URL, takie jak /
są kodowane w adresie URL.
resource
resource
to bieżąca wartość w usłudze reprezentowana jako mapa par klucz-wartość. Odwołanie resource
w ramach warunku spowoduje co najwyżej jeden odczyt wartości z usługi. To wyszukiwanie będzie wliczane do limitu zasobu związanego z usługą. W przypadku żądań get
resource
będzie wliczany do limitu tylko w przypadku odmowy.
Operatory i pierwszeństwo operatorów
Skorzystaj z poniższej tabeli jako odniesienia do operatorów i ich odpowiedniego pierwszeństwa w Regułach dotyczących Cloud Firestore i Cloud Storage.
Biorąc b
a
pole f
i indeks i
.
Operator | Opis | Łączność |
---|---|---|
a[i] a() af | Indeks, połączenie, dostęp do pola | od lewej do prawej | !a -a | Jednoargumentowa negacja | od prawej do lewej |
a/ba%ba*b | Operatory multiplikatywne | od lewej do prawej |
a+b ab | Operatory addytywne | od lewej do prawej |
a>ba>=ba | Operatorzy relacyjni | od lewej do prawej |
a in b | Istnienie na liście lub mapie | od lewej do prawej |
a is type | Porównanie typów, gdzie type może być bool, int, float, liczba, ciąg znaków, lista, mapa, znacznik czasu, czas trwania, ścieżka lub latlng | od lewej do prawej |
a==ba!=b | Operatory porównania | od lewej do prawej | a && b | Warunkowe ORAZ | od lewej do prawej |
a || b | Warunkowe LUB | od lewej do prawej |
a ? true_value : false_value | Wyrażenie trójskładnikowe | od lewej do prawej |
Baza danych czasu rzeczywistego
Warunek to wyrażenie logiczne określające, czy dana operacja powinna być dozwolona, czy zabroniona. Możesz zdefiniować te warunki w Regułach bazy danych czasu rzeczywistego w następujący sposób.
Wstępnie zdefiniowane zmienne
Istnieje wiele przydatnych, predefiniowanych zmiennych, do których można uzyskać dostęp w definicji reguły. Oto krótkie podsumowanie każdego z nich:
Predefiniowane zmienne | |
---|---|
Teraz | Bieżący czas w milisekundach od epoki Linuksa. Działa to szczególnie dobrze w przypadku sprawdzania znaczników czasu utworzonych za pomocą pliku firebase.database.ServerValue.TIMESTAMP pakietu SDK. |
źródło | RuleDataSnapshot reprezentujący ścieżkę główną w bazie danych Firebase, jaka istniała przed próbą wykonania operacji. |
nowe dane | RuleDataSnapshot reprezentujący dane w postaci, w jakiej istniałyby po próbie wykonania operacji. Obejmuje zapisywane nowe dane i istniejące dane. |
dane | RuleDataSnapshot reprezentujący dane w stanie, w jakim istniały przed próbą wykonania operacji. |
$ zmienne | Ścieżka z symbolem wieloznacznym używana do reprezentowania identyfikatorów i dynamicznych kluczy podrzędnych. |
autoryzacja | Reprezentuje ładunek tokenu uwierzytelnionego użytkownika. |
Tych zmiennych można używać w dowolnym miejscu reguł. Na przykład poniższe reguły bezpieczeństwa zapewniają, że dane zapisywane w węźle /foo/
muszą być ciągiem krótszym niż 100 znaków:
{ "rules": { "foo": { // /foo is readable by the world ".read": true, // /foo is writable by the world ".write": true, // data written to /foo must be a string less than 100 characters ".validate": "newData.isString() && newData.val().length < 100" } } }
Reguły oparte na danych
Wszelkie dane z Twojej bazy danych mogą zostać wykorzystane w Twoich regułach. Używając predefiniowanych zmiennych root
, data
i newData
, możesz uzyskać dostęp do dowolnej ścieżki, jaka istniałaby przed lub po zdarzeniu zapisu.
Rozważmy ten przykład, który pozwala na operacje zapisu, o ile wartość węzła /allow_writes/
jest true
, węzeł nadrzędny nie ma ustawionej flagi readOnly
, a w nowo zapisanych danych znajduje się element podrzędny o nazwie foo
:
".write": "root.child('allow_writes').val() === true && !data.parent().child('readOnly').exists() && newData.child('foo').exists()"
Reguły oparte na zapytaniach
Chociaż nie możesz używać reguł jako filtrów, możesz ograniczyć dostęp do podzbiorów danych, używając parametrów zapytania w swoich regułach. Użyj query.
wyrażenia w regułach, aby przyznać dostęp do odczytu lub zapisu na podstawie parametrów zapytania.
Na przykład poniższa reguła oparta na zapytaniach wykorzystuje reguły bezpieczeństwa oparte na użytkownikach i reguły oparte na zapytaniach, aby ograniczyć dostęp do danych w kolekcji baskets
tylko do koszyków zakupów, których właścicielem jest aktywny użytkownik:
"baskets": {
".read": "auth.uid !== null &&
query.orderByChild === 'owner' &&
query.equalTo === auth.uid" // restrict basket access to owner of basket
}
Poniższe zapytanie, które zawiera parametry zapytania w regule, powiedzie się:
db.ref("baskets").orderByChild("owner")
.equalTo(auth.currentUser.uid)
.on("value", cb) // Would succeed
Jednak zapytania, które nie zawierają parametrów w regule, nie powiodą się z powodu błędu PermissionDenied
:
db.ref("baskets").on("value", cb) // Would fail with PermissionDenied
Możesz także użyć reguł opartych na zapytaniach, aby ograniczyć ilość danych pobieranych przez klienta w ramach operacji odczytu.
Na przykład poniższa reguła ogranicza dostęp do odczytu tylko do pierwszych 1000 wyników zapytania, uporządkowanych według priorytetu:
messages: {
".read": "query.orderByKey &&
query.limitToFirst <= 1000"
}
// Example queries:
db.ref("messages").on("value", cb) // Would fail with PermissionDenied
db.ref("messages").limitToFirst(1000)
.on("value", cb) // Would succeed (default order by key)
Poniższe query.
wyrażenia są dostępne w Regułach zabezpieczeń bazy danych czasu rzeczywistego.
Wyrażenia reguł oparte na zapytaniach | ||
---|---|---|
Wyrażenie | Typ | Opis |
zapytanie.zamówienieByKey zapytanie.orderByPriority zapytanie.zamówienieWedługWartości | wartość logiczna | To prawda w przypadku zapytań uporządkowanych według klucza, priorytetu lub wartości. Inaczej nieprawda. |
zapytanie.zamówieniePrzezDziecko | strunowy zero | Użyj ciągu znaków do reprezentowania ścieżki względnej do węzła podrzędnego. Na przykład query.orderByChild === "address/zip" . Jeśli zapytanie nie jest uporządkowane przez węzeł podrzędny, ta wartość ma wartość null. |
zapytanie.startAt zapytanie.endAt zapytanie.równeTo | strunowy numer wartość logiczna zero | Pobiera granice wykonującego zapytania lub zwraca wartość null, jeśli nie ma zestawu powiązań. |
zapytanie.limitToFirst zapytanie.limitToLast | numer zero | Pobiera limit wykonywanego zapytania lub zwraca wartość null, jeśli nie ustawiono żadnego limitu. |
Operatorzy
Reguły bazy danych czasu rzeczywistego obsługują wiele operatorów, których można używać do łączenia zmiennych w instrukcji warunku. Zobacz pełną listę operatorów w dokumentacji referencyjnej .
Tworzenie warunków
Rzeczywiste warunki będą się różnić w zależności od dostępu, jaki chcesz przyznać. Reguły celowo oferują ogromny stopień elastyczności, dzięki czemu reguły Twojej aplikacji mogą ostatecznie być tak proste lub tak złożone, jak tego potrzebujesz.
Aby uzyskać wskazówki dotyczące tworzenia prostych, gotowych do użycia w środowisku produkcyjnym reguł, zobacz Podstawowe reguły zabezpieczeń .