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