获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

Data de validade

Você pode usar as regras de segurança do Firebase para gravar condicionalmente novos dados com base nos dados existentes em seu banco de dados ou depósito de armazenamento. Você também pode escrever regras que imponham validações de dados restringindo as 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 as regras de validação de dados.

Restrições sobre novos dados

Cloud Firestore

Se você quiser garantir que um documento que contém um campo específico não seja criado, inclua o campo na condição de allow . Por exemplo, se você quiser negar a criação de quaisquer documentos que contenham o campo de ranking , desabilite-o na condição de 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ê deseja garantir que os dados que contêm determinados valores não sejam adicionados ao seu banco de dados, inclua esse valor em suas regras e não permita gravações. Por exemplo, se quiser negar quaisquer gravações que contenham valores de ranking , você não permitiria gravações de quaisquer documentos com valores de 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 você quiser garantir que um arquivo que contém metadados específicos não seja criado, inclua os metadados na condição de allow . Por exemplo, se você quiser negar a criação de quaisquer arquivos que contenham metadados de ranking , desabilite-os na condição de 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 Firestore

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 de 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 foi alterado, que um campo foi incrementado apenas em um ou que o novo valor esteja pelo menos uma semana no futuro. Nesse caso, se seu conjunto de regras permitir a gravação pendente, a variável request.resource conterá o estado futuro do documento. Para operações de update que apenas modificam 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 as regras .validate para impor estruturas de dados e validar o formato e o conteúdo dos dados. As regras executam regras .validate depois de verificar se uma regra .write concede acesso.

As regras .validate não são colocadas em cascata. Se alguma regra de validação falhar em qualquer caminho ou subcaminho na 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 todas as solicitações que estão 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()"
        }
      }
    }
  }

As solicitações de gravação em um banco de dados com as regras acima teriam 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);
Objective-C
Observação: este produto Firebase não está disponível no destino App Clip.
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
Observação: este produto Firebase não está disponível no destino App Clip.
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);
DESCANSO
# 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 as regras, você também pode querer 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 arquivos maiores que um determinado tamanho a serem excluídos.

O objeto de 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 de read ou write para garantir a integridade dos dados. O objeto de resource verifica metadados em arquivos existentes em seu intervalo 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 de 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 de resource está disponível na documentação de referência .