С помощью Firebase Security Rules можно условно записывать новые данные на основе существующих данных в базе данных или хранилище. Также можно создавать правила, которые обеспечивают проверку данных, ограничивая запись в зависимости от типа записываемых данных. Подробнее о правилах, использующих существующие данные для создания условий безопасности, читайте далее.
Выберите товар в каждом разделе, чтобы узнать больше о правилах проверки данных.
Ограничения на предоставление новых данных
Cloud Firestore
Если вы хотите гарантировать, что документ, содержащий определенное поле, не будет создан, вы можете включить это поле в условие allow . Например, если вы хотите запретить создание любых документов, содержащих поле ranking , вы должны запретить это в условии create .
service cloud.firestore {
match /databases/{database}/documents {
// Disallow
match /cities/{city} {
allow create: if !("ranking" in request.resource.data)
}
}
}
Realtime Database
Если вы хотите убедиться, что данные, содержащие определенные значения, не добавляются в вашу базу данных, вам следует включить это значение в ваши правила и запретить его запись. Например, если вы хотите запретить любую запись, содержащую значения ranking , вам следует запретить запись для любых документов, содержащих значения ranking .
{
"rules": {
// Write is allowed for all paths
".write": true,
// Allows writes only if new data doesn't include a `ranking` child value
".validate": "!newData.hasChild('ranking')
}
}
Cloud Storage
Если вы хотите гарантировать, что файл, содержащий определенные метаданные, не будет создан, вы можете включить эти метаданные в условие allow . Например, если вы хотите запретить создание любых файлов, содержащих метаданные ranking , вы должны указать это в условии create .
service firebase.storage {
match /b/{bucket}/o {
match /files/{fileName} {
// Disallow
allow create: if !("ranking" in request.resource.metadata)
}
}
}
Используйте существующие данные в Firebase Security Rules
Cloud Firestore
Многие приложения хранят информацию о контроле доступа в виде полей документов в базе данных. Cloud Firestore Security Rules могут динамически разрешать или запрещать доступ на основе данных документа:
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to read data if the document has the 'visibility'
// field set to 'public'
match /cities/{city} {
allow read: if resource.data.visibility == 'public';
}
}
}
Переменная resource указывает на запрошенный документ, а resource.data представляет собой карту всех полей и значений, хранящихся в документе. Для получения дополнительной информации о переменной resource см. справочную документацию .
При записи данных может потребоваться сравнение входящих данных с существующими. Это позволяет, например, убедиться, что поле не изменилось, что значение поля увеличилось только на единицу, или что новое значение будет получено не ранее чем через неделю. В этом случае, если ваш набор правил разрешает ожидающую запись, переменная request.resource будет содержать текущее состояние документа. Для операций update , которые изменяют только подмножество полей документа, переменная request.resource будет содержать ожидающее состояние документа после операции. Вы можете проверить значения полей в request.resource , чтобы предотвратить нежелательные или несогласованные обновления данных:
service cloud.firestore {
match /databases/{database}/documents {
// Make sure all cities have a positive population and
// the name is not changed
match /cities/{city} {
allow update: if request.resource.data.population > 0
&& request.resource.data.name == resource.data.name;
}
}
}
Realtime Database
В Realtime Database используйте правила .validate для проверки структуры данных и подтверждения формата и содержимого данных. Rules .validate выполняются после проверки того, что правило .write предоставляет доступ.
Правила .validate не имеют каскадного действия. Если какое-либо правило проверки не проходит по какому-либо пути или подпути в правиле, вся операция записи будет отклонена. Кроме того, определения проверки проверяют только ненулевые значения и, следовательно, игнорируют любые запросы на удаление данных.
Рассмотрим следующие правила .validate :
{
"rules": {
// write is allowed for all paths
".write": true,
"widget": {
// a valid widget must have attributes "color" and "size"
// allows deleting widgets (since .validate is not applied to delete rules)
".validate": "newData.hasChildren(['color', 'size'])",
"size": {
// the value of "size" must be a number between 0 and 99
".validate": "newData.isNumber() &&
newData.val() >= 0 &&
newData.val() <= 99"
},
"color": {
// the value of "color" must exist as a key in our mythical
// /valid_colors/ index
".validate": "root.child('valid_colors/' + newData.val()).exists()"
}
}
}
}
Запросы на запись в базу данных, использующую указанные выше правила, приведут к следующим результатам:
JavaScript
var ref = db.ref("/widget"); // PERMISSION_DENIED: does not have children color and size ref.set('foo'); // PERMISSION DENIED: does not have child color ref.set({size: 22}); // PERMISSION_DENIED: size is not a number ref.set({ size: 'foo', color: 'red' }); // SUCCESS (assuming 'blue' appears in our colors list) ref.set({ size: 21, color: 'blue'}); // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child('size').set(99);
Objective-C
FIRDatabaseReference *ref = [[[FIRDatabase database] reference] child: @"widget"]; // PERMISSION_DENIED: does not have children color and size [ref setValue: @"foo"]; // PERMISSION DENIED: does not have child color [ref setValue: @{ @"size": @"foo" }]; // PERMISSION_DENIED: size is not a number [ref setValue: @{ @"size": @"foo", @"color": @"red" }]; // SUCCESS (assuming 'blue' appears in our colors list) [ref setValue: @{ @"size": @21, @"color": @"blue" }]; // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate [[ref child:@"size"] setValue: @99];
Быстрый
var ref = FIRDatabase.database().reference().child("widget") // PERMISSION_DENIED: does not have children color and size ref.setValue("foo") // PERMISSION DENIED: does not have child color ref.setValue(["size": "foo"]) // PERMISSION_DENIED: size is not a number ref.setValue(["size": "foo", "color": "red"]) // SUCCESS (assuming 'blue' appears in our colors list) ref.setValue(["size": 21, "color": "blue"]) // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child("size").setValue(99);
Java
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("widget"); // PERMISSION_DENIED: does not have children color and size ref.setValue("foo"); // PERMISSION DENIED: does not have child color ref.child("size").setValue(22); // PERMISSION_DENIED: size is not a number Map<String,Object> map = new HashMap<String, Object>(); map.put("size","foo"); map.put("color","red"); ref.setValue(map); // SUCCESS (assuming 'blue' appears in our colors list) map = new HashMap<String, Object>(); map.put("size", 21); map.put("color","blue"); ref.setValue(map); // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child("size").setValue(99);
ОТДЫХ
# PERMISSION_DENIED: does not have children color and size
curl -X PUT -d 'foo' \
https://docs-examples.firebaseio.com/rest/securing-data/example.json
# PERMISSION DENIED: does not have child color
curl -X PUT -d '{"size": 22}' \
https://docs-examples.firebaseio.com/rest/securing-data/example.json
# PERMISSION_DENIED: size is not a number
curl -X PUT -d '{"size": "foo", "color": "red"}' \
https://docs-examples.firebaseio.com/rest/securing-data/example.json
# SUCCESS (assuming 'blue' appears in our colors list)
curl -X PUT -d '{"size": 21, "color": "blue"}' \
https://docs-examples.firebaseio.com/rest/securing-data/example.json
# If the record already exists and has a color, this will
# succeed, otherwise it will fail since newData.hasChildren(['color', 'size'])
# will fail to validate
curl -X PUT -d '99' \
https://docs-examples.firebaseio.com/rest/securing-data/example/size.jsonCloud Storage
При оценке правил также может потребоваться оценить метаданные загружаемого, скачиваемого, изменяемого или удаляемого файла. Это позволяет создавать сложные и мощные правила, которые, например, разрешают загрузку только файлов с определенными типами содержимого или удаление только файлов определенного размера.
Объект resource содержит пары ключ-значение с метаданными файлов, отображаемыми в объекте Cloud Storage . Эти свойства можно проверить при запросах на read или write , чтобы обеспечить целостность данных. Объект resource проверяет метаданные существующих файлов в вашем сегменте Cloud Storage .
service firebase.storage {
match /b/{bucket}/o {
match /images {
match /{fileName} {
// Allow reads if a custom 'visibility' field is set to 'public'
allow read: if resource.metadata.visibility == 'public';
}
}
}
}
Вы также можете использовать объект request.resource для запросов на write (например, для загрузки, обновления метаданных и удаления). Объект request.resource получает метаданные из файла, которые будут записаны, если write разрешена.
Эти два значения можно использовать для предотвращения нежелательных или противоречивых обновлений, а также для обеспечения соблюдения ограничений приложения, таких как тип или размер файла.
service firebase.storage {
match /b/{bucket}/o {
match /images {
// Allow write files to the path "images/*", subject to the constraints:
// 1) File is less than 5MB
// 2) Content type is an image
// 3) Uploaded content type matches existing content type
// 4) Filename (stored in imageId wildcard variable) is less than 32 characters
match /{imageId} {
allow read;
allow write: if request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*')
&& request.resource.contentType == resource.contentType
&& imageId.size() < 32
}
}
}
}
Полный список свойств объекта resource доступен в справочной документации .