了解 2023 年 Google I/O 大会上介绍的 Firebase 亮点。了解详情

Условия использования в правилах безопасности Firebase Cloud Storage

Это руководство основано на изучении основного синтаксиса руководства по языку правил безопасности Firebase, чтобы показать, как добавлять условия в ваши правила безопасности Firebase для облачного хранилища.

Основным составным элементом правил безопасности облачного хранилища является условие . Условие — это логическое выражение, определяющее, следует ли разрешить или запретить конкретную операцию. Для базовых правил использование true и false литералов в качестве условий отлично работает. Но язык Firebase Security Rules for Cloud Storage дает вам возможность писать более сложные условия, которые могут:

  • Проверить аутентификацию пользователя
  • Проверять входящие данные

Аутентификация

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

Когда аутентифицированный пользователь выполняет запрос к Cloud Storage, переменная request.auth заполняется uid пользователя ( request.auth.uid ), а также утверждениями Firebase Authentication JWT ( request.auth.token ).

Кроме того, при использовании пользовательской проверки подлинности в поле request.auth.token появляются дополнительные утверждения.

Когда неавторизованный пользователь выполняет запрос, переменная request.auth имеет значение null .

Используя эти данные, существует несколько распространенных способов использования аутентификации для защиты файлов:

  • Общедоступно: игнорировать request.auth
  • Аутентифицированный частный: убедитесь, что request.auth не равен null
  • Частный пользователь: убедитесь, что request.auth.uid совпадает с uid пути
  • Частная группа: проверьте утверждения пользовательского токена на соответствие выбранному утверждению или прочитайте метаданные файла, чтобы узнать, существует ли поле метаданных.

Общественный

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

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

Аутентифицированный частный

В некоторых случаях вы можете захотеть, чтобы данные были доступны для просмотра всем пользователям вашего приложения, прошедшим проверку подлинности, но не пользователям, не прошедшим проверку подлинности. Поскольку переменная request.auth имеет null для всех неаутентифицированных пользователей, все, что вам нужно сделать, это проверить существование переменной request.auth , чтобы требовать аутентификацию:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

Личный пользователь

На сегодняшний день наиболее распространенным вариантом использования request.auth будет предоставление отдельным пользователям детальных разрешений на их файлы: от загрузки изображений профиля до чтения личных документов.

Поскольку файлы в облачном хранилище имеют полный «путь» к файлу, все, что требуется для того, чтобы сделать файл контролируемым пользователем, — это часть уникальной информации, идентифицирующей пользователя, в префиксе имени файла (например, uid пользователя), которую можно проверить. когда правило оценивается:

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth.uid == userId;
}

Групповое приватное

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

  • Создайте пользовательский токен Firebase Authentication, который содержит дополнительную информацию о члене группы (например, идентификатор группы).
  • Включить информацию о группе (например, идентификатор группы или список авторизованных uid ) в метаданные файла .

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

// 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;
}

Запросить оценку

Загрузки, загрузки, изменения метаданных и удаления оцениваются с использованием request отправленного в облачное хранилище. В дополнение к уникальному идентификатору пользователя и полезной нагрузке Firebase Authentication в объекте request.auth , как описано выше, переменная request содержит путь к файлу, в котором выполняется запрос, время получения запроса и новое значение resource , если запрос на запись.

Объект request также содержит уникальный идентификатор пользователя и полезную нагрузку Firebase Authentication в объекте request.auth , что будет объяснено далее в разделе «Безопасность на основе пользователей» документации.

Полный список свойств в объекте request доступен ниже:

Свойство Тип Описание
auth карта<строка, строка> Когда пользователь входит в систему, предоставляет uid , уникальный идентификатор пользователя и token , карту утверждений Firebase Authentication JWT. В противном случае он будет null .
params карта<строка, строка> Карта, содержащая параметры запроса запроса.
path путь path , представляющий путь, по которому выполняется запрос.
resource карта<строка, строка> Новое значение ресурса, присутствующее только в запросах write .
time отметка времени Временная метка, представляющая время сервера, в которое оценивается запрос.

Оценка ресурсов

При оценке правил вы также можете оценить метаданные загружаемого, загружаемого, изменяемого или удаляемого файла. Это позволяет создавать сложные и мощные правила, которые разрешают загрузку только файлов с определенным типом содержимого или удаление только файлов, превышающих определенный размер.

Правила безопасности Firebase для облачного хранилища предоставляют метаданные файла в объекте resource , который содержит пары «ключ-значение» метаданных, отображаемых в объекте облачного хранилища. Эти свойства можно проверять при запросах на read или write для обеспечения целостности данных.

В запросах write (таких как загрузка, обновление метаданных и удаление) в дополнение к объекту resource , который содержит метаданные файла для файла, который в настоящее время существует по пути запроса, у вас также есть возможность использовать объект request.resource , который содержит подмножество метаданных файла для записи, если запись разрешена. Эти два значения можно использовать для обеспечения целостности данных или принудительного применения ограничений приложения, таких как тип или размер файла.

Полный список свойств в resource объекте доступен ниже:

Свойство Тип Описание
name нить Полное название объекта
bucket нить Имя корзины, в которой находится этот объект.
generation инт Создание объекта Google Cloud Storage для этого объекта.
metageneration инт Метагенерация объекта Google Cloud Storage этого объекта.
size инт Размер объекта в байтах.
timeCreated отметка времени Отметка времени, представляющая время создания объекта.
updated отметка времени Отметка времени, представляющая время последнего обновления объекта.
md5Hash нить Хэш MD5 объекта.
crc32c нить Хэш crc32c объекта.
etag нить Тег, связанный с этим объектом.
contentDisposition нить Расположение содержимого, связанное с этим объектом.
contentEncoding нить Кодировка содержимого, связанная с этим объектом.
contentLanguage нить Язык содержимого, связанный с этим объектом.
contentType нить Тип содержимого, связанный с этим объектом.
metadata карта<строка, строка> Пары ключ/значение дополнительных настраиваемых метаданных, указанных разработчиком.

request.resource содержит все это, за исключением generation , metageneration , etag , timeCreated и updated .

Расширьте возможности с помощью Cloud Firestore

Вы можете получить доступ к документам в Cloud Firestore, чтобы оценить другие критерии авторизации.

Используя функции firestore.get() и firestore.exists() , ваши правила безопасности могут оценивать входящие запросы относительно документов в Cloud Firestore. Обе функции firestore.get() и firestore.exists() предполагают полностью указанные пути к документам. При использовании переменных для создания путей для firestore.get() и firestore.exists() вам необходимо явно экранировать переменные, используя синтаксис $(variable) .

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

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{club}/files/{fileId} {
      allow read: if club in
        firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships
    }
  }
}
В следующем примере только друзья пользователя могут видеть его фотографии.
service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/photos/{fileId} {
      allow read: if
        firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id))
    }
  }
}

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

Вы можете отключить эту функцию, удалив роль IAM, как описано в разделе Управление и развертывание правил безопасности Firebase .

Проверить данные

Правила безопасности Firebase для облачного хранилища также можно использовать для проверки данных, включая проверку имени файла и пути, а также свойств метаданных файла, таких как contentType и size .

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

Пользовательские функции

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

  • Функции могут содержать только один оператор return . Они не могут содержать никакой дополнительной логики. Например, они не могут выполнять циклы или вызывать внешние службы.
  • Функции могут автоматически обращаться к функциям и переменным из области, в которой они определены. Например, функция, определенная в области действия service firebase.storage имеет доступ к переменной resource , а только для Cloud Firestore — к встроенным функциям, таким как get() и exists() .
  • Функции могут вызывать другие функции, но не могут рекурсивно выполняться. Общая глубина стека вызовов ограничена 10.
  • В версии rules2 функции могут определять переменные с помощью ключевого слова let . Функции могут иметь любое количество привязок let, но должны заканчиваться оператором return.

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

service firebase.storage {
  match /b/{bucket}/o {
    // 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 /images/{imageId} {
      allow read, write: if signedInOrPublic();
    }
    match /mp3s/{mp3Ids} {
      allow read: if signedInOrPublic();
    }
  }
}

Использование функций в ваших правилах безопасности Firebase делает их более удобными в сопровождении по мере роста сложности ваших правил.

Следующие шаги

После обсуждения условий вы получили более глубокое понимание правил и готовы:

Узнайте, как работать с основными вариантами использования, и изучите рабочий процесс разработки, тестирования и развертывания правил: