Você pode usar as regras de segurança do Firebase para gravar novos dados condicionalmente com base nos dados existentes em seu banco de dados ou bucket de armazenamento. Você também pode escrever regras que imponham validações de dados restringindo gravações com base nos novos dados que estão sendo gravados. Continue lendo para saber mais sobre regras que usam dados existentes para criar condições de segurança.
Selecione um produto em cada seção para saber mais sobre regras de validação de dados.
Restrições sobre novos dados
Cloud Fire Store
Se quiser ter certeza de que um documento que contém um campo específico não será criado, você poderá incluir o campo na condição allow
. Por exemplo, se quiser negar a criação de quaisquer documentos que contenham o campo ranking
, você deverá proibi-lo na condição create
.
service cloud.firestore {
match /databases/{database}/documents {
// Disallow
match /cities/{city} {
allow create: if !("ranking" in request.resource.data)
}
}
}
Banco de dados em tempo real
Se você quiser ter certeza de que os dados que contêm determinados valores não serão adicionados ao seu banco de dados, você incluiria esse valor em suas regras e não permitiria gravações. Por exemplo, se quiser negar qualquer gravação que contenha valores ranking
, você deverá proibir gravações para quaisquer documentos com valores 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')
}
}
Armazenamento na núvem
Se quiser ter certeza de que um arquivo que contém metadados específicos não será criado, você poderá incluir os metadados na condição allow
. Por exemplo, se você quiser negar a criação de qualquer arquivo que contenha metadados ranking
, você deverá proibi-lo na condição create
.
service firebase.storage {
match /b/{bucket}/o {
match /files/{allFiles=**} {
// Disallow
allow create: if !("ranking" in request.resource.metadata)
}
}
}
Use dados existentes nas regras de segurança do Firebase
Cloud Fire Store
Muitos aplicativos armazenam informações de controle de acesso como campos em documentos no banco de dados. As regras de segurança do Cloud Firestore podem permitir ou negar acesso dinamicamente com base nos dados do documento:
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';
}
}
}
A variável resource
refere-se ao documento solicitado e resource.data
é um mapa de todos os campos e valores armazenados no documento. Para obter mais informações sobre a variável resource
, consulte a documentação de referência .
Ao gravar dados, você pode querer comparar os dados recebidos com os dados existentes. Isso permite que você faça coisas como garantir que um campo não tenha sido alterado, que um campo tenha aumentado apenas em um ou que o novo valor seja pelo menos uma semana no futuro. Neste caso, se o seu conjunto de regras permitir a gravação pendente, a variável request.resource
conterá o estado futuro do documento. Para operações update
que modificam apenas um subconjunto dos campos do documento, a variável request.resource
conterá o estado do documento pendente após a operação. Você pode verificar os valores dos campos em request.resource
para evitar atualizações de dados indesejadas ou inconsistentes:
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;
}
}
}
Banco de dados em tempo real
No Realtime Database, use regras .validate
para impor estruturas de dados e validar o formato e o conteúdo dos dados. As regras executam regras .validate
após verificar se uma regra .write
concede acesso.
As regras .validate
não são cascatas. Se alguma regra de validação falhar em qualquer caminho ou subcaminho da regra, toda a operação de gravação será rejeitada. Além disso, as definições de validação verificam apenas valores não nulos e, subsequentemente, ignoram quaisquer solicitações que estejam excluindo dados.
Considere as seguintes regras .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()"
}
}
}
}
Escrever solicitações em um banco de dados com as regras acima teria os seguintes resultados:
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);
Objetivo-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];
Rápido
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);
DESCANSAR
# 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.json
Armazenamento na núvem
Ao avaliar regras, você também pode avaliar os metadados do arquivo que está sendo carregado, baixado, modificado ou excluído. Isso permite que você crie regras complexas e poderosas que fazem coisas como permitir apenas o upload de arquivos com determinados tipos de conteúdo ou apenas a exclusão de arquivos maiores que um determinado tamanho.
O objeto resource
contém pares de chave/valor com metadados de arquivo exibidos em um objeto do Cloud Storage. Essas propriedades podem ser inspecionadas em solicitações read
ou write
para garantir a integridade dos dados. O objeto resource
verifica metadados em arquivos existentes no bucket do Cloud Storage.
service firebase.storage {
match /b/{bucket}/o {
match /images {
match /{allImages=**} {
// Allow reads if a custom 'visibility' field is set to 'public'
allow read: if resource.metadata.visibility == 'public';
}
}
}
}
Você também pode usar o objeto request.resource
em solicitações write
(como uploads, atualizações de metadados e exclusões. O objeto request.resource
obtém metadados do arquivo que será gravado se a write
for permitida.
Você pode usar esses dois valores para evitar atualizações indesejadas ou inconsistentes ou para impor restrições de aplicativo, como tipo ou tamanho de arquivo.
service firebase.storage {
match /b/{bucket}/o {
match /images {
// Cascade read to any image type at any path
match /{allImages=**} {
allow read;
}
// 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) File name (stored in imageId wildcard variable) is less than 32 characters
match /{imageId} {
allow write: if request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*')
&& request.resource.contentType == resource.contentType
&& imageId.size() < 32
}
}
}
}
Uma lista completa de propriedades no objeto resource
está disponível na documentação de referência .