Podstawowe reguły zabezpieczeń

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 FirestoreRealtime 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 DatabaseCloud 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 FirestoreRealtime 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 roszczeniaFirebase 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;
  }
}