Условия использования в правилах безопасности облачного хранилища Firebase

Это руководство, основанное на руководстве по изучению основного синтаксиса Firebase Security Rules показывает, как добавлять условия в Firebase Security Rules для Cloud Storage .

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

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

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

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

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

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

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

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

  • Общедоступно: игнорировать request.auth
  • Аутентифицированный приватный доступ: проверьте, не null ли 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 будет предоставление отдельным пользователям детальных прав доступа к своим файлам: от загрузки фотографий профиля до чтения личных документов.

Поскольку файлы в Cloud Storage имеют полный «путь» к файлу, для того чтобы сделать файл управляемым пользователем, достаточно уникальной информации, идентифицирующей пользователя, содержащейся в префиксе имени файла (например, 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 отправленного в Cloud Storage . В дополнение к уникальному идентификатору пользователя и полезной нагрузке Firebase Authentication в объекте request.auth , как описано выше, переменная request содержит путь к файлу, в котором выполняется запрос, время получения запроса и новое значение resource , если запрос является запросом на запись.

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

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

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

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

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

Firebase Security Rules для Cloud Storage предоставляют метаданные файлов в объекте resource , который содержит пары ключ/значение метаданных, отображаемых в объекте Cloud Storage . Эти свойства можно проверять при запросах на 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 нить etag, связанный с этим объектом.
contentDisposition нить Содержимое, связанное с данным объектом.
contentEncoding нить Кодировка содержимого, связанная с этим объектом.
contentLanguage нить Язык контента, связанный с этим объектом.
contentType нить Тип содержимого, связанный с этим объектом.
metadata map<string, string> Пары ключ/значение дополнительных, заданных разработчиком пользовательских метаданных.

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)).data.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 Storage Security Rules , использующих функции Cloud Firestore , в консоли Firebase или Firebase CLI вам будет предложено включить разрешения для подключения двух продуктов.

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

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

Firebase Security Rules для Cloud Storage также можно использовать для проверки данных, включая проверку имени и пути файла, а также свойств метаданных файла, таких как 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 Security Rules вам может потребоваться обернуть наборы условий в функции, которые можно повторно использовать во всем наборе правил. Правила безопасности поддерживают пользовательские функции. Синтаксис пользовательских функций немного похож на 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 Security Rules упрощает их сопровождение по мере роста сложности правил.

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

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

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