Podstawowe reguły zabezpieczeń

Firebase Security Rules umożliwiają kontrolowanie dostępu do przechowywanych danych. Dzięki elastycznej składni reguł możesz tworzyć reguły, które pasują do wszystkiego – od wszystkich operacji zapisu 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 zaimplementować 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 o ich działaniu.

Aby uzyskać dostęp do reguł i je zaktualizować, wykonaj czynności opisane w artykule Zarządzanie regułami bezpieczeństwa Firebase i ich wdrażanieFirebase Security Rules.

Reguły domyślne: tryb zablokowany

Podczas tworzenia bazy danych lub instancji pamięci w konsoli Firebase, możesz wybrać, czy Firebase Security Rules mają ograniczać dostęp do danych (tryb zablokowany) czy zezwalać na dostęp każdemu (tryb testowy). W Cloud Firestore i Realtime Database, domyślne reguły w trybie zablokowanym odmawiają dostępu wszystkim użytkownikom. W Cloud Storage dostęp do zbiorów danych 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. Zanim wdrożysz aplikację w środowisku produkcyjnym, pamiętaj o zaktualizowaniu Security Rules przed Pamiętaj też, że jeśli wdrożysz aplikację, będzie ona dostępna publicznie – nawet jeśli jej nie opublikujesz.

Pamiętaj, że Firebase umożliwia klientom bezpośredni dostęp do Twoich danych, a Firebase Security Rules są jedynym zabezpieczeniem blokującym dostęp złośliwym użytkownikom. Definiowanie reguł oddzielnie od logiki produktu ma wiele zalet: klienci nie są odpowiedzialni za egzekwowanie bezpieczeństwa, błędne implementacje nie naruszą Twoich danych, a co najważniejsze, nie musisz polegać na serwerze pośredniczącym, aby chronić dane przed światem.

Wszyscy uwierzytelnieni użytkownicy

Nie zalecamy pozostawiania danych dostępnych dla każdego zalogowanego użytkownika, 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 użytku produkcyjnego

Podczas przygotowywania aplikacji do wdrożenia upewnij się, że dane są chronione, a dostęp do nich jest prawidłowo przyznany użytkownikom. Aby skonfigurować dostęp oparty na użytkownikach, użyj Authentication, a aby skonfigurować dostęp oparty na danych, odczytuj dane bezpośrednio z bazy danych.

Podczas strukturyzowania danych warto pisać reguły, ponieważ sposób ich skonfigurowania 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 1 użytkownika, a ścieżka danych zawiera jego identyfikator.

Kiedy ta reguła działa: ta reguła sprawdza się, gdy dane są odizolowane od 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 żądający dostępu 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 danej ś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ą elementów dostępnych publicznie, ale muszą ograniczać dostęp do edycji tylko do właścicieli tych elementów. Na przykład aplikacja do czatowania lub blog.

Kiedy ta reguła nie działa: podobnie jak reguła dostępu tylko dla 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 dostęp do odczytu 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 te reguły działały, musisz zdefiniować i przypisać atrybuty użytkownikom w swoich danych. Firebase Security Rules sprawdzają żądanie na podstawie danych z bazy danych lub metadanych pliku , aby potwierdzić lub odrzucić dostęp.

Kiedy ta reguła działa: 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 swoim przedmiocie) oraz grupy „dyrektorzy” (odczyt wszystkich treści).

Kiedy ta reguła nie działa: W Realtime Database i Cloud Storage, Twoje reguły nie mogą używać metody get(), którą mogą zawierać reguły Cloud Firestore. W związku z tym 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żna odczytać, a następnie skonstruuj regułę tak, aby odczytywała to pole i warunkowo przyznawała dostęp. W Realtime Database utwórz ścieżkę danych, która definiuje użytkowników aplikacji i przyznaje im rolę w węźle podrzędnym.

Możesz też skonfigurować niestandardowe deklaracje w Authentication a następnie pobrać te informacje z auth.token zmiennej w dowolnych Firebase Security Rules.

Atrybuty i role zdefiniowane w danych

Te reguły działają tylko w Cloud Firestore i Realtime Database.

Cloud Firestore

Pamiętaj, że za każdym razem, gdy reguły zawierają odczyt, np. reguły poniżej, naliczana jest opłata za operację odczytu 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 deklaracji niestandardowych

Aby zaimplementować te reguły, skonfiguruj niestandardowe deklaracje w Firebase Authentication a następnie użyj tych deklaracji 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 dzierżawy

Aby zaimplementować te reguły, skonfiguruj współdzielenie zasobów 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ślonym najemcy, 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;
  }
}