Основные правила безопасности

Firebase Security Rules позволяют вам контролировать доступ к сохраненным данным. Гибкий синтаксис правил означает, что вы можете создавать правила, которые соответствуют чему угодно: от всех операций записи во всю базу данных до операций над конкретным документом.

В этом руководстве описаны некоторые из наиболее простых вариантов использования, которые вы, возможно, захотите реализовать при настройке приложения и защите своих данных. Однако прежде чем приступить к написанию правил, возможно, вам захочется узнать больше о языке , на котором они написаны, и их поведении .

Чтобы получить доступ к своим правилам и обновить их, выполните действия, описанные в разделе «Управление и развертывание Firebase Security Rules .

Правила по умолчанию: заблокированный режим

Когда вы создаете экземпляр базы данных или хранилища в консоли Firebase , вы выбираете, ограничивают ли ваши Firebase Security Rules доступ к вашим данным ( режим блокировки ) или разрешают кому-либо доступ ( тестовый режим ). В Cloud Firestore и Realtime Database правила по умолчанию для режима блокировки запрещают доступ всем пользователям. В Cloud Storage только прошедшие проверку подлинности пользователи могут получить доступ к сегментам хранилища.

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 request.auth != null;
    }
  }
}

Правила среды разработки

Пока вы работаете над своим приложением, вам может потребоваться относительно открытый или беспрепятственный доступ к вашим данным. Просто обязательно обновите свои Rules перед развертыванием приложения в рабочей среде. Также помните, что если вы развернете свое приложение, оно станет общедоступным, даже если вы его еще не запустили .

Помните, что Firebase предоставляет клиентам прямой доступ к вашим данным, а Firebase Security Rules — единственная защита, блокирующая доступ злоумышленников. Определение правил отдельно от логики продукта имеет ряд преимуществ: клиенты не несут ответственности за обеспечение безопасности, ошибочные реализации не поставят под угрозу ваши данные и, что наиболее важно, вы не полагаетесь на промежуточный сервер для защиты данных от внешнего мира.

Все авторизованные пользователи

Хотя мы не рекомендуем оставлять ваши данные доступными любому пользователю, вошедшему в систему, может быть полезно настроить доступ для любого пользователя, прошедшего проверку подлинности, во время разработки приложения.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Realtime Database

{
  "rules": {
    ".read": "auth.uid !== null",
    ".write": "auth.uid !== null"
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Готовые к производству правила

Готовясь к развертыванию приложения, убедитесь, что ваши данные защищены и что вашим пользователям предоставлен доступ. Используйте Authentication для настройки доступа на основе пользователей и читайте непосредственно из вашей базы данных для настройки доступа на основе данных.

Рассмотрите возможность написания правил при структурировании данных, поскольку способ настройки правил влияет на то, как вы ограничиваете доступ к данным по различным путям.

Доступ только для владельцев контента

Эти правила ограничивают доступ только проверенному владельцу контента. Данные доступны для чтения и записи только одному пользователю, а путь к данным содержит идентификатор пользователя.

Когда это правило работает: Это правило хорошо работает, если данные разделены по пользователям — если единственным пользователем, которому нужен доступ к данным, является тот же пользователь, который создал данные.

Когда это правило не работает: этот набор правил не работает, когда нескольким пользователям необходимо записать или прочитать одни и те же данные — пользователи перезапишут данные или не смогут получить доступ к созданным ими данным.

Чтобы настроить это правило: Создайте правило, которое подтверждает, что пользователь, запрашивающий доступ для чтения или записи данных, является пользователем, которому принадлежат эти данные.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow only authenticated content owners access
    match /some_collection/{userId}/{documents=**} {
      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>/path/to/file.txt"
    match /user/{userId}/{allPaths=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

Смешанный публичный и частный доступ

Это правило позволяет любому читать набор данных, но ограничивает возможность создавать или изменять данные по заданному пути только авторизованному владельцу контента.

Когда это правило работает: это правило хорошо работает для приложений, которым требуются общедоступные элементы, но которым необходимо ограничить доступ к редактированию владельцам этих элементов. Например, приложение для чата или блог.

Когда это правило не работает: как и правило только для владельца контента, этот набор правил не работает, когда несколько пользователей должны редактировать одни и те же данные. В конечном итоге пользователи перезапишут данные друг друга.

Чтобы настроить это правило: Создайте правило, которое разрешает доступ на чтение для всех пользователей (или всех прошедших проверку подлинности пользователей) и подтверждает, что пользователь, записывающий данные, является владельцем.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      allow read: if true
      allow create: if request.auth.uid == request.resource.data.author_uid;
      allow update, 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>/path/to/file.txt"
    match /user/{userId}/{allPaths=**} {
      allow read;
      allow write: if request.auth.uid == userId;
    }
  }
}

Доступ на основе атрибутов и ролей

Чтобы эти правила работали, вы должны определить и назначить атрибуты пользователям в ваших данных. Firebase Security Rules проверяют запрос на соответствие данным из вашей базы данных или метаданным файла, чтобы подтвердить или запретить доступ.

Когда это правило работает: если вы назначаете роль пользователям, это правило позволяет легко ограничить доступ на основе ролей или определенных групп пользователей. Например, если вы храните оценки, вы можете назначить разные уровни доступа группе «Учащиеся» (только чтение их содержимого), группе «Учителя» (чтение и запись по своему предмету) и группе «Директора» (чтение весь контент).

Когда это правило не работает: в Realtime Database и Cloud Storage ваши правила не могут использовать метод get() , который могут включать правила Cloud Firestore . Следовательно, вам необходимо структурировать свою базу данных или метаданные файла так, чтобы они отражали атрибуты, которые вы используете в своих правилах.

Чтобы настроить это правило: в Cloud Firestore включите в документы пользователей поле, которое вы можете прочитать, затем структурируйте свое правило для чтения этого поля и условно предоставьте доступ. В Realtime Database создайте путь к данным, который определяет пользователей вашего приложения и предоставляет им роль в дочернем узле.

Вы также можете настроить собственные утверждения в разделе Authentication , а затем получить эту информацию из переменной auth.token в любых Firebase Security Rules .

Определяемые данными атрибуты и роли

Эти правила работают только в Cloud Firestore и Realtime Database .

Cloud Firestore

Помните, что каждый раз, когда ваши правила включают чтение, как в правилах ниже, вам выставляется счет за операцию чтения в 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
      }
    }
  }
}

Атрибуты и роли настраиваемых утверждений

Чтобы реализовать эти правила, настройте собственные утверждения в Firebase Authentication , а затем используйте утверждения в своих правилах.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, check for an admin 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 leverage
        ".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;
  }
}

Атрибуты аренды

Чтобы реализовать эти правила, настройте мультиарендность в Google Cloud Identity Platform (GCIP), а затем используйте арендатора в своих правилах. Следующие примеры разрешают запись от пользователя в определенном клиенте, например 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;
  }
}