Это руководство основано на изучении основного синтаксиса руководства по языку 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
), а также утверждениями 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
будет предоставление отдельным пользователям детализированных разрешений на доступ к их файлам: от загрузки фотографий профиля до чтения личных документов.
Поскольку файлы в 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 | карта<строка, строка> | Когда пользователь вошел в систему, предоставляет uid , уникальный идентификатор пользователя, и token , карту утверждений Firebase Authentication JWT. В противном случае это будет null . |
params | карта<строка, строка> | Карта, содержащая параметры запроса. |
path | путь | path представляющий путь, по которому выполняется запрос. |
resource | карта<строка, строка> | Новое значение ресурса, присутствующее только в запросах write . |
time | временная метка | Временная метка, представляющая время сервера, когда оценивается запрос. |
Оценка ресурсов
При оценке правил вы также можете захотеть оценить метаданные загружаемого, скачиваемого, изменяемого или удаляемого файла. Это позволяет вам создавать сложные и мощные правила, которые делают такие вещи, как разрешают загрузку только файлов с определенными типами контента или удаление только файлов, превышающих определенный размер.
Firebase Security Rules for 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 | нить | Тег e, связанный с этим объектом. |
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 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 .