Firebase Security Rules umożliwiają kontrolowanie dostępu do przechowywanych danych. Elastyczna składnia reguł oznacza, że możesz tworzyć reguły pasujące do dowolnych elementów, od wszystkich zapisów w całej bazie danych po operacje na konkretnym dokumencie.
W tym przewodniku opisujemy niektóre z bardziej podstawowych przypadków użycia, które możesz wdrożyć podczas konfigurowania aplikacji i zabezpieczania danych. Zanim jednak zaczniesz pisać reguły, warto dowiedzieć się więcej o języku, w którym są one pisane, i ich działaniu.
Aby uzyskać dostęp do reguł i je zaktualizować, wykonaj czynności opisane w artykule Zarządzanie Firebase Security Rules i wdrażanie.
Reguły domyślne: tryb blokady
Gdy tworzysz bazę danych lub instancję pamięci w FirebasekonsoliFirebase Security Rules, możesz wybrać, czy Firebase Security Rulesograniczyć dostęp do danych (tryb zablokowany), czy zezwolić na dostęp wszystkim użytkownikom (tryb testowy). W przypadku Cloud Firestore i Realtime Database domyślne reguły trybu zablokowanego odmawiają dostępu wszystkim użytkownikom. W Cloud Storage dostęp do zasobników miejsca na dane mają tylko uwierzytelnieni użytkownicy.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
Realtime Database
{
"rules": {
".read": false,
".write": false
}
}
Cloud Storage
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if false;
}
}
}
Reguły środowiska programistycznego
Podczas pracy nad aplikacją możesz potrzebować stosunkowo otwartego lub nieograniczonego dostępu do danych. Pamiętaj tylko, aby zaktualizować Rules przed wdrożeniem aplikacji w wersji produkcyjnej. Pamiętaj też, że jeśli wdrożysz aplikację, będzie ona publicznie dostępna, nawet jeśli jej nie uruchomisz.
Pamiętaj, że Firebase umożliwia klientom bezpośredni dostęp do Twoich danych, a Firebase Security Rules to jedyne zabezpieczenie blokujące dostęp złośliwym użytkownikom. Określanie reguł oddzielnie od logiki usługi ma wiele zalet: klienci nie są odpowiedzialni za egzekwowanie bezpieczeństwa, wadliwe implementacje nie zagrażają Twoim danym, a co najważniejsze, nie polegasz na serwerze pośredniczącym w ochronie danych przed światem.
Wszyscy uwierzytelnieni użytkownicy
Nie zalecamy udostępniania danych wszystkim zalogowanym użytkownikom, ale podczas tworzenia aplikacji może być przydatne ustawienie dostępu dla każdego uwierzytelnionego użytkownika.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
match /some_collection/{document} {
allow read, write: if request.auth != null;
}
}
}
Realtime Database
{
"rules": {
"some_path": {
".read": "auth.uid !== null",
".write": "auth.uid !== null"
}
}
}
Cloud Storage
service firebase.storage {
match /b/{bucket}/o {
match /some_folder/{fileName} {
allow read, write: if request.auth != null;
}
}
}
Reguły gotowe do wykorzystania w środowisku produkcyjnym
Podczas przygotowywania aplikacji do wdrożenia zadbaj o ochronę danych i prawidłowe przyznanie dostępu użytkownikom. Użyj Authentication, aby skonfigurować dostęp oparty na użytkownikach, i odczytuj dane bezpośrednio z bazy danych, aby skonfigurować dostęp oparty na danych.
Reguły warto tworzyć podczas strukturyzowania danych, ponieważ sposób ich konfiguracji wpływa na to, jak ograniczasz dostęp do danych w różnych ścieżkach.
Dostęp tylko dla właściciela treści
Te reguły ograniczają dostęp tylko do uwierzytelnionego właściciela treści. Dane mogą być odczytywane i zapisywane tylko przez jednego użytkownika, a ścieżka danych zawiera jego identyfikator.
Kiedy ta reguła działa: ta reguła sprawdza się, gdy dane są odseparowane od siebie według użytkownika – jeśli jedynym użytkownikiem, który musi mieć dostęp do danych, jest ten sam użytkownik, który je utworzył.
Kiedy ta reguła nie działa: ten zestaw reguł nie działa, gdy wielu użytkowników musi zapisywać lub odczytywać te same dane – użytkownicy będą nadpisywać dane lub nie będą mogli uzyskać dostępu do utworzonych przez siebie danych.
Aby skonfigurować tę regułę: utwórz regułę, która potwierdza, że użytkownik, który prosi o dostęp do odczytu lub zapisu danych, jest właścicielem tych danych.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
// Allow only authenticated content owners access
match /some_collection/{userId}/{document} {
allow read, write: if request.auth != null && request.auth.uid == userId
}
}
}
Realtime Database
{
"rules": {
"some_path": {
"$uid": {
// Allow only authenticated content owners access to their data
".read": "auth !== null && auth.uid === $uid",
".write": "auth !== null && auth.uid === $uid"
}
}
}
}
Cloud Storage
// Grants a user access to a node matching their user ID
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "user/<UID>/file.txt"
match /user/{userId}/{fileName} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
Mieszany dostęp publiczny i prywatny
Ta reguła umożliwia każdemu odczytywanie zbioru danych, ale ogranicza możliwość tworzenia lub modyfikowania danych w danym ścieżce tylko do uwierzytelnionego właściciela treści.
Kiedy ta reguła działa: ta reguła sprawdza się w przypadku aplikacji, które wymagają publicznie dostępnych elementów, ale muszą ograniczać dostęp do edycji tych elementów do ich właścicieli. Może to być np. aplikacja do obsługi czatu lub blog.
Kiedy ta reguła nie działa: podobnie jak reguła dotycząca tylko właściciela treści, ten zestaw reguł nie działa, gdy wielu użytkowników musi edytować te same dane. Użytkownicy będą ostatecznie nadpisywać dane innych użytkowników.
Aby skonfigurować tę regułę: utwórz regułę, która umożliwia odczyt wszystkim użytkownikom (lub wszystkim uwierzytelnionym użytkownikom) i potwierdza, że użytkownik zapisujący dane jest ich właścicielem.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
// Allow public read access, but only content owners can write
match /some_collection/{document} {
// Allow public reads
allow read: if true
// Allow creation if the current user owns the new document
allow create: if request.auth.uid == request.resource.data.author_uid;
// Allow updates by the owner, and prevent change of ownership
allow update: if request.auth.uid == request.resource.data.author_uid
&& request.auth.uid == resource.data.author_uid;
// Allow deletion if the current user owns the existing document
allow delete: if request.auth.uid == resource.data.author_uid;
}
}
}
Realtime Database
{
// Allow anyone to read data, but only authenticated content owners can
// make changes to their data
"rules": {
"some_path": {
"$uid": {
".read": true,
// or ".read": "auth.uid !== null" for only authenticated users
".write": "auth.uid === $uid"
}
}
}
}
Cloud Storage
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "user/<UID>/file.txt"
match /user/{userId}/{fileName} {
allow read;
allow write: if request.auth.uid == userId;
}
}
}
Dostęp oparty na atrybutach i rolach
Aby ta reguła działała, musisz zdefiniować atrybuty i przypisać je użytkownikom w swoich danych. Firebase Security Rules sprawdza żądanie na podstawie danych z bazy danych lub metadanych pliku, aby potwierdzić lub odrzucić dostęp.
Działanie reguły: jeśli przypisujesz rolę użytkownikom, ta reguła umożliwia ograniczenie dostępu na podstawie ról lub określonych grup użytkowników. Jeśli na przykład przechowujesz oceny, możesz przypisać różne poziomy dostępu do grupy „uczniowie” (tylko odczyt treści), grupy „nauczyciele” (odczyt i zapis w ramach swojego przedmiotu) oraz grupy „dyrektorzy” (odczyt wszystkich treści).
Kiedy ta reguła nie działa: w przypadku Realtime Database i Cloud Storage reguły nie mogą korzystać z metody get()
, którą mogą uwzględniać reguły Cloud Firestore.
Dlatego musisz tak skonstruować metadane bazy danych lub pliku, aby odzwierciedlały atrybuty używane w regułach.
Aby skonfigurować tę regułę: w Cloud Firestore dodaj do dokumentów użytkowników pole, które możesz odczytać, a następnie skonfiguruj regułę tak, aby odczytywała to pole i warunkowo przyznawała dostęp. W Realtime Database utwórz ścieżkę danych, która określa użytkowników aplikacji i przyznaje im rolę w węźle podrzędnym.
Możesz też skonfigurować niestandardowe roszczenia w Authentication, a następnie pobrać te informacje ze zmiennej auth.token
w dowolnym Firebase Security Rules.
Atrybuty i role zdefiniowane przez dane
Te reguły działają tylko w Cloud Firestore i Realtime Database.
Cloud Firestore
Pamiętaj, że za każdym razem, gdy reguły obejmują odczyt, np. reguły poniżej, za operację odczytu pobierana jest opłata w Cloud Firestore.
service cloud.firestore {
match /databases/{database}/documents {
// For attribute-based access control, Check a boolean `admin` attribute
allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
allow read: true;
// Alterntatively, for role-based access, assign specific roles to users
match /some_collection/{document} {
allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer"
}
}
}
Realtime Database
{
"rules": {
"some_path": {
"${subpath}": {
//
".write": "root.child('users').child(auth.uid).child('role').val() === 'admin'",
".read": true
}
}
}
}
Atrybuty i role niestandardowe
Aby wdrożyć te reguły, skonfiguruj niestandardowe roszczenia w Firebase Authentication, a następnie użyj ich w regułach.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
// For attribute-based access control, check for an administrator claim
allow write: if request.auth.token.admin == true;
allow read: true;
// Alterntatively, for role-based access, assign specific roles to users
match /some_collection/{document} {
allow read: if request.auth.token.reader == "true";
allow write: if request.auth.token.writer == "true";
}
}
}
Realtime Database
{
"rules": {
"some_path": {
"$uid": {
// Create a custom claim for each role or group
// you want to use
".write": "auth.uid !== null && auth.token.writer === true",
".read": "auth.uid !== null && auth.token.reader === true"
}
}
}
}
Cloud Storage
service firebase.storage {
// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
allow read: if resource.metadata.owner == request.auth.token.groupId;
allow write: if request.auth.token.groupId == groupId;
}
}
Atrybuty najmu
Aby wdrożyć te reguły, skonfiguruj wielodostępność w Google Cloud Identity Platform (GCIP), a następnie użyj najemcy w regułach. Poniższe przykłady umożliwiają zapisywanie danych przez użytkownika w określonej domenie, np. tenant2-m6tyz
.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
// For tenant-based access control, check for a tenantID
allow write: if request.auth.token.firebase.tenant == 'tenant2-m6tyz';
allow read: true;
}
}
Realtime Database
{
"rules": {
"some_path": {
"$uid": {
// Only allow reads and writes if user belongs to a specific tenant
".write": "auth.uid !== null && auth.token.firebase.tenant === 'tenant2-m6tyz'",
".read": "auth.uid !== null
}
}
}
}
Cloud Storage
service firebase.storage {
// Only allow reads and writes if user belongs to a specific tenant
match /files/{tenantId}/{fileName} {
allow read: if request.auth != null;
allow write: if request.auth.token.firebase.tenant == tenantId;
}
}