Estruture as regras de segurança

As regras de segurança do Firestore permitem-lhe controlar o acesso a documentos e coleções na sua base de dados. A sintaxe de regras flexíveis permite-lhe criar regras que correspondem a qualquer coisa, desde todas as escritas na base de dados inteira até operações num documento específico.

Este guia descreve a sintaxe e a estrutura básicas das regras de segurança. Combine esta sintaxe com condições das regras de segurança para criar conjuntos de regras completos.

Declaração de serviço e base de dados

As regras de segurança do Firestore começam sempre com a seguinte declaração:

service cloud.firestore {
  // The {database} wildcard allows the rules to reference any database,
  // but these rules are only active on databases where they are explicitly deployed.
  match /databases/{database}/documents {
    // ...
  }
}

A declaração service cloud.firestore limita o âmbito das regras ao Firestore, o que evita conflitos entre as regras de segurança do Firestore e as regras de outros produtos, como o Cloud Storage.

A declaração match /databases/{database}/documents especifica que as regras devem corresponder a qualquer base de dados do Firestore no projeto. Embora um projeto possa conter até 100 bases de dados, apenas a primeira base de dados criada é designada como predefinição.

As regras de segurança do Firestore são aplicadas separadamente a cada base de dados com nome no seu projeto. Isto significa que, se criar várias bases de dados, tem de gerir e implementar regras para cada uma individualmente. Para ver instruções detalhadas sobre a implementação das atualizações, consulte o artigo Implemente as suas atualizações.

Regras básicas de leitura/escrita

As regras básicas consistem numa declaração match que especifica um caminho do documento e numa expressão allow que detalha quando a leitura dos dados especificados é permitida:

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

Todas as declarações de correspondência devem apontar para documentos e não para coleções. Uma declaração de correspondência pode apontar para um documento específico, como em match /cities/SF, ou usar carateres universais para apontar para qualquer documento no caminho especificado, como em match /cities/{city}.

No exemplo acima, a declaração de correspondência usa a sintaxe de caráter universal {city}. Isto significa que a regra se aplica a qualquer documento na coleção cities, como /cities/SF ou /cities/NYC. Quando as expressões allow na declaração de correspondência são avaliadas, a variável city é resolvida para o nome do documento da cidade, como SF ou NYC.

Operações detalhadas

Em algumas situações, é útil dividir read e write em operações mais detalhadas. Por exemplo, a sua app pode querer aplicar condições diferentes à criação de documentos do que à eliminação de documentos. Em alternativa, pode querer permitir leituras de documentos únicos, mas recusar consultas grandes.

Uma regra read pode ser dividida em get e list, enquanto uma regra write pode ser dividida em create, update e delete:

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
}

Dados hierárquicos

Os dados no Firestore estão organizados em coleções de documentos e cada documento pode expandir a hierarquia através de subcoleções. É importante compreender como as regras de segurança interagem com os dados hierárquicos.

Considere a situação em que cada documento na coleção cities contém uma subcoleção landmarks. As regras de segurança aplicam-se apenas ao caminho correspondente, pelo que os controlos de acesso definidos na coleção cities não se aplicam à subcoleção landmarks. Em alternativa, escreva regras explícitas para controlar o acesso a subcoleções:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

Quando aninham declarações match, o caminho da declaração match interior é sempre relativo ao caminho da declaração match exterior. Por isso, os seguintes conjuntos de regras são equivalentes:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

Carateres universais recursivos

Se quiser que as regras se apliquem a uma hierarquia arbitrariamente profunda, use a sintaxe de caráter universal recursivo, {name=**}. Por exemplo:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

Quando usa a sintaxe de caráter universal recursivo, a variável de caráter universal contém o segmento do caminho correspondente completo, mesmo que o documento esteja localizado numa subcoleção profundamente aninhada. Por exemplo, as regras indicadas acima corresponderiam a um documento localizado em /cities/SF/landmarks/coit_tower, e o valor da variável document seria SF/landmarks/coit_tower.

No entanto, tenha em atenção que o comportamento dos carateres universais recursivos depende da versão das regras.

Versão 1

As regras de segurança usam a versão 1 por predefinição. Na versão 1, os carateres universais recursivos correspondem a um ou mais itens de caminho. Não correspondem a um caminho vazio, pelo que match /cities/{city}/{document=**} corresponde a documentos em subcoleções, mas não na coleção cities, enquanto match /cities/{document=**} corresponde a documentos na coleção cities e nas subcoleções.

Os carateres universais recursivos têm de aparecer no final de uma declaração de correspondência.

Versão 2

Na versão 2 das regras de segurança, os carateres universais recursivos correspondem a zero ou mais itens do caminho. match/cities/{city}/{document=**} corresponde a documentos em quaisquer subcoleções, bem como a documentos na coleção cities.

Tem de aderir à versão 2 adicionando rules_version = '2'; na parte superior das regras de segurança:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

Pode ter, no máximo, um caráter universal recursivo por declaração de correspondência, mas na versão 2, pode colocar este caráter universal em qualquer parte da declaração de correspondência. Por exemplo:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

Se usar consultas de grupos de recolha, tem de usar a versão 2. Consulte o artigo sobre como proteger consultas de grupos de recolha.

Declarações de correspondência sobrepostas

É possível que um documento corresponda a mais do que uma declaração match. No caso em que várias expressões allow correspondem a um pedido, o acesso é permitido se qualquer uma das condições for true:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

No exemplo acima, todas as leituras e escritas na coleção cities são permitidas porque a segunda regra é sempre true, mesmo que a primeira regra seja sempre false.

Limites das regras de segurança

Quando trabalhar com regras de segurança, tenha em atenção os seguintes limites:

Limite Detalhes
Número máximo de chamadas exists(), get() e getAfter() por pedido
  • 10 para pedidos de documentos únicos e pedidos de consultas.
  • 20 para leituras de vários documentos, transações e gravações em lote. O limite anterior de 10 também se aplica a cada operação.

    Por exemplo, imagine que cria um pedido de gravação em lote com 3 operações de gravação e que as suas regras de segurança usam 2 chamadas de acesso a documentos para validar cada gravação. Neste caso, cada gravação usa 2 das suas 10 chamadas de acesso e o pedido de gravação em lote usa 6 das suas 20 chamadas de acesso.

Se exceder qualquer um dos limites, recebe um erro de acesso negado.

Algumas chamadas de acesso a documentos podem ser colocadas em cache e as chamadas em cache não contam para os limites.

Profundidade máxima da declaração match aninhada 10
Comprimento máximo do caminho, em segmentos do caminho, permitido num conjunto de declarações aninhadas match 100
Número máximo de variáveis de captura de caminho permitidas num conjunto de declarações match aninhadas 20
Profundidade máxima de chamadas de funções 20
Número máximo de argumentos de funções 7
Número máximo de associações de variáveis let por função 10
Número máximo de chamadas de funções recursivas ou cíclicas 0 &lpar;não permitido&rpar;
Número máximo de expressões avaliadas por pedido 1000
Tamanho máximo de um conjunto de regras Os conjuntos de regras têm de obedecer a dois limites de tamanho:
  • Um limite de 256 KB no tamanho da origem do texto do conjunto de regras publicado a partir da consola do Firebase ou da CLI através de firebase deploy.
  • Um limite de 250 KB no tamanho do conjunto de regras compilado que resulta quando o Firebase processa a origem e a torna ativa no back-end.

Passos seguintes