Ir para o console

Linguagem das regras de segurança

As regras de segurança do Firebase utilizam linguagens flexíveis, avançadas e personalizadas que são compatíveis com uma ampla variedade de complexidade e granularidade. É possível tornar suas regras específicas ou gerais, dependendo do que fizer sentido para seu aplicativo. As regras do Realtime Database usam uma sintaxe que parece JavaScript em uma estrutura JSON. As regras do Cloud Firestore e do Cloud Storage usam uma linguagem baseada na Common Expression Language (CEL), com instruções match e allow que são compatíveis com o acesso concedido de modo condicional.

No entanto, como essas linguagens são personalizadas, há uma curva de aprendizado. Use este guia para entender melhor a linguagem das regras conforme você lidar mais com regras mais complexas.

Selecione um produto para saber mais sobre as regras dele.

Estrutura básica

Cloud Firestore

As regras de segurança do Firebase no Cloud Firestore e no Storage usam as seguintes estrutura e sintaxe:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

Veja abaixo os principais conceitos que você precisa conhecer antes de criar as regras

  • Solicitação: o método ou os métodos invocados na instrução allow que você permite serem executados. Os métodos padrão são: get, list, create, update e delete. Os métodos de conveniência read e write permitem amplo acesso de leitura e gravação ao banco de dados ou ao caminho de armazenamento especificado.
  • Caminho: o banco de dados ou o local de armazenamento, representado como um caminho de URI.
  • Regra: a instrução allow com uma condição que permitirá a ocorrência de uma solicitação se ela for avaliada como verdadeira.

Cada um desses conceitos é descrito em mais detalhes abaixo.

Cloud Storage

As regras de segurança do Firebase no Cloud Firestore e no Storage usam as seguintes estrutura e sintaxe:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

Veja abaixo os principais conceitos que você precisa conhecer antes de criar as regras

  • Solicitação: o método ou os métodos invocados na instrução allow que você permite serem executados. Os métodos padrão são: get, list, create, update e delete. Os métodos de conveniência read e write permitem amplo acesso de leitura e gravação ao banco de dados ou ao caminho de armazenamento especificado.
  • Caminho: o banco de dados ou o local de armazenamento, representado como um caminho de URI.
  • Regra: a instrução allow com uma condição que permitirá a ocorrência de uma solicitação se ela for avaliada como verdadeira.

Cada um desses conceitos é descrito em mais detalhes abaixo.

Realtime Database

No Realtime Database, as regras de segurança do Firebase consistem em expressões semelhantes a JavaScript contidas em um documento JSON.

Elas usam a seguinte sintaxe:

{
  "rules": {
    "<<path>>": {
    // Allow the request if the condition for each method is true.
      ".read": <<condition>>,
      ".write": <<condition>>,
      ".validate": <<condition>>
    }
  }
}

Existem três elementos básicos na regra:

  • Caminho: o local do banco de dados. Ele corresponde à estrutura JSON do seu banco de dados.
  • Solicitação: são os métodos que a regra usa para conceder acesso. As regras read e write concedem acesso amplo de leitura e gravação. Já as regras validate atuam como uma verificação secundária para conceder acesso com base nos dados novos ou nos existentes.
  • Condição: a condição que permitirá uma solicitação se ela for avaliada como verdadeira.

Blocos de regras

Cloud Firestore

Veja a seguir os elementos básicos de uma regra no Cloud Firestore e no Cloud Storage:

  • A declaração service: informa a qual produto do Firebase as regras se aplicam.
  • O bloco match: define um caminho no banco de dados ou no intervalo de armazenamento ao qual as regras se aplicam.
  • A instrução allow: fornece condições para conceder acesso, diferenciadas por métodos. Os métodos compatíveis incluem: get, list, create, update, delete e os métodos de conveniência read e write.
  • Declarações function opcionais: permitem combinar e agrupar condições para uso em várias regras.

O service contém um ou mais blocos match com instruções allow que fornecem condições para conceder acesso a solicitações. As variáveis request e resource estão disponíveis para uso nas condições da regra. A linguagem das regras de segurança do Firebase também é compatível com declarações function.

Serviço

A declaração service define para qual produto ou serviço do Firebase as regras se aplicam. É possível incluir apenas uma declaração service por arquivo de origem.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Storage

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

Se estiver definindo regras para o Cloud Firestore e o Storage usando a Firebase CLI, você precisará mantê-las em arquivos separados.

Correspondência

Um bloco match declara um padrão path que tem correspondência com o caminho da operação solicitada (o request.path de entrada). O corpo de match precisa ter um ou mais blocos match aninhados, instruções allow ou declarações function. O caminho em blocos match aninhados é relativo ao caminho no bloco match pai.

O padrão path é um nome semelhante a um diretório que pode incluir variáveis ou caracteres curinga. O padrão path permite correspondências de segmento de caminho único e de segmento de vários caminhos. Qualquer variável vinculada em um path é visível no escopo match ou em qualquer escopo aninhado em que o path seja declarado.

As correspondências com um padrão path podem ser parciais ou completas:

  • Correspondências parciais: o padrão path é uma correspondência de prefixo do request.path.
  • Correspondências completas: o padrão path corresponde a todo o request.path.

Quando uma correspondência completa ocorre, as regras dentro do bloco são avaliadas. Quando uma correspondência parcial acontece, as regras match aninhadas são testadas para verificar se algum path aninhado completará a correspondência.

As regras em cada correspondência (match) completa são avaliadas para determinar se a solicitação será permitida. Se qualquer regra correspondente conceder acesso, a solicitação será permitida. Se nenhuma regra correspondente conceder acesso, a solicitação será negada.

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

Conforme o exemplo acima, as declarações path são compatíveis com as seguintes variáveis:

  • Caractere curinga de segmento único: uma variável de caractere curinga é declarada em um caminho ao colocar uma variável entre chaves: {variable}. Essa variável pode ser acessada dentro da instrução match como uma string.
  • Caractere curinga recursivo: o caractere curinga recursivo, ou de vários segmentos, corresponde a vários segmentos em um caminho ou abaixo dele. Ele corresponde a todos os caminhos abaixo do local para o qual você o definiu. Para declará-lo, adicione a string =** ao final da variável do seu segmento: {variable=**}. Essa variável pode ser acessada dentro da instrução match como um objeto path.

Permitir

O bloco match contém uma ou mais instruções allow. Essas são as regras de fato. É possível aplicar regras allow a um ou mais métodos. As condições de uma instrução allow precisam ser avaliadas como verdadeiras para que o Cloud Firestore ou o Storage conceda qualquer solicitação recebida. É possível também escrever instruções allow sem condições, por exemplo, allow read. No entanto, se a instrução allow não incluir uma condição, ela permitirá a solicitação desse método por padrão.

Se qualquer uma das regras allow do método for atendida, a solicitação será permitida. Além disso, se uma regra mais ampla conceder acesso, as regras concederão acesso e ignorarão as mais específicas que possam limitá-lo.

Veja o exemplo a seguir, em que qualquer usuário pode ler ou excluir os próprios arquivos. Uma regra mais específica só permitirá gravações se o arquivo estiver no formato PNG e pertencer ao usuário solicitante. Um usuário pode excluir qualquer arquivo no subcaminho, mesmo que não esteja em PNG, porque a regra anterior permite essa ação.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth.uid == userId && imageId.matches('*.png');
  }
}

Método

Cada instrução allow inclui um método que concede acesso a solicitações recebidas do mesmo método.

Método Tipo de solicitação
Métodos de conveniência
read Qualquer tipo de solicitação de leitura
write Qualquer tipo de solicitação de gravação
Métodos padrão
get Ler solicitações de documentos ou arquivos únicos
list Ler solicitações de consultas e conjuntos
create Gravar novos documentos ou arquivos
update Gravar em documentos ou arquivos existentes
delete Excluir dados

Não é possível sobrepor métodos de leitura no mesmo bloco match ou métodos de gravação conflitantes na mesma declaração path.

Por exemplo, as seguintes regras apresentariam falha:

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all unauthenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth.uid == "me";
    }
  }
}

Função

À medida que suas regras de segurança se tornam mais complexas, recomendamos reunir conjuntos de condições em funções que possam ser reutilizadas no seu conjunto de regras. As regras de segurança dão suporte a funções personalizadas. A sintaxe para funções personalizadas é um pouco parecida com JavaScript, mas as funções de regras de segurança são escritas em uma linguagem de programação específica de domínio com algumas limitações importantes:

  • As funções podem conter apenas uma única instrução return. Elas não podem conter nenhuma lógica adicional. Por exemplo, as funções não podem criar variáveis intermediárias, executar loops ou chamar serviços externos.
  • As funções podem acessar automaticamente funções e variáveis do escopo em que são definidas. Por exemplo, uma função definida no escopo service cloud.firestore tem acesso à variável resource e a funções integradas, como get() e exists().
  • Elas podem chamar outras funções, mas não são executadas novamente. A profundidade total da pilha de chamadas é limitada a 20.

Uma função é definida com a palavra-chave function e pode utilizar argumentos ou não. Por exemplo, pode ser necessário combinar os dois tipos de condição usados nos exemplos acima em uma única função:

service cloud.firestore {
  match /databases/{database}/documents {
    // 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 /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

O uso de funções nas regras de segurança as torna mais fáceis de atualizar à medida que a complexidade delas aumenta.

Cloud Storage

Veja a seguir os elementos básicos de uma regra no Cloud Firestore e no Cloud Storage:

  • A declaração service: informa a qual produto do Firebase as regras se aplicam.
  • O bloco match: define um caminho no banco de dados ou no intervalo de armazenamento ao qual as regras se aplicam.
  • A instrução allow: fornece condições para conceder acesso, diferenciadas por métodos. Os métodos compatíveis incluem: get, list, create, update, delete e os métodos de conveniência read e write.
  • Declarações function opcionais: permitem combinar e agrupar condições para uso em várias regras.

O service contém um ou mais blocos match com instruções allow que fornecem condições para conceder acesso a solicitações. As variáveis request e resource estão disponíveis para uso nas condições da regra. A linguagem das regras de segurança do Firebase também é compatível com declarações function.

Serviço

A declaração service define para qual produto ou serviço do Firebase as regras se aplicam. É possível incluir apenas uma declaração service por arquivo de origem.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Storage

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

Se estiver definindo regras para o Cloud Firestore e o Storage usando a Firebase CLI, você precisará mantê-las em arquivos separados.

Correspondência

Um bloco match declara um padrão path que tem correspondência com o caminho da operação solicitada (o request.path de entrada). O corpo de match precisa ter um ou mais blocos match aninhados, instruções allow ou declarações function. O caminho em blocos match aninhados é relativo ao caminho no bloco match pai.

O padrão path é um nome semelhante a um diretório que pode incluir variáveis ou caracteres curinga. O padrão path permite correspondências de segmento de caminho único e de segmento de vários caminhos. Qualquer variável vinculada em um path é visível no escopo match ou em qualquer escopo aninhado em que o path seja declarado.

As correspondências com um padrão path podem ser parciais ou completas:

  • Correspondências parciais: o padrão path é uma correspondência de prefixo do request.path.
  • Correspondências completas: o padrão path corresponde a todo o request.path.

Quando uma correspondência completa ocorre, as regras dentro do bloco são avaliadas. Quando uma correspondência parcial acontece, as regras match aninhadas são testadas para verificar se algum path aninhado completará a correspondência.

As regras em cada correspondência (match) completa são avaliadas para determinar se a solicitação será permitida. Se qualquer regra correspondente conceder acesso, a solicitação será permitida. Se nenhuma regra correspondente conceder acesso, a solicitação será negada.

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

Conforme o exemplo acima, as declarações path são compatíveis com as seguintes variáveis:

  • Caractere curinga de segmento único: uma variável de caractere curinga é declarada em um caminho ao colocar uma variável entre chaves: {variable}. Essa variável pode ser acessada dentro da instrução match como uma string.
  • Caractere curinga recursivo: o caractere curinga recursivo, ou de vários segmentos, corresponde a vários segmentos em um caminho ou abaixo dele. Ele corresponde a todos os caminhos abaixo do local para o qual você o definiu. Para declará-lo, adicione a string =** ao final da variável do seu segmento: {variable=**}. Essa variável pode ser acessada dentro da instrução match como um objeto path.

Permitir

O bloco match contém uma ou mais instruções allow. Essas são as regras de fato. É possível aplicar regras allow a um ou mais métodos. As condições de uma instrução allow precisam ser avaliadas como verdadeiras para que o Cloud Firestore ou o Storage conceda qualquer solicitação recebida. É possível também escrever instruções allow sem condições, por exemplo, allow read. No entanto, se a instrução allow não incluir uma condição, ela permitirá a solicitação desse método por padrão.

Se qualquer uma das regras allow do método for atendida, a solicitação será permitida. Além disso, se uma regra mais ampla conceder acesso, as regras concederão acesso e ignorarão as mais específicas que possam limitá-lo.

Veja o exemplo a seguir, em que qualquer usuário pode ler ou excluir os próprios arquivos. Uma regra mais específica só permitirá gravações se o arquivo estiver no formato PNG e pertencer ao usuário solicitante. Um usuário pode excluir qualquer arquivo no subcaminho, mesmo que não esteja em PNG, porque a regra anterior permite essa ação.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth.uid == userId && imageId.matches('*.png');
  }
}

Método

Cada instrução allow inclui um método que concede acesso a solicitações recebidas do mesmo método.

Método Tipo de solicitação
Métodos de conveniência
read Qualquer tipo de solicitação de leitura
write Qualquer tipo de solicitação de gravação
Métodos padrão
get Ler solicitações de documentos ou arquivos únicos
list Ler solicitações de consultas e conjuntos
create Gravar novos documentos ou arquivos
update Gravar em documentos ou arquivos existentes
delete Excluir dados

Não é possível sobrepor métodos de leitura no mesmo bloco match ou métodos de gravação conflitantes na mesma declaração path.

Por exemplo, as seguintes regras apresentariam falha:

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all unauthenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth.uid == "me";
    }
  }
}

Função

À medida que suas regras de segurança se tornam mais complexas, recomendamos reunir conjuntos de condições em funções que possam ser reutilizadas no seu conjunto de regras. As regras de segurança dão suporte a funções personalizadas. A sintaxe para funções personalizadas é um pouco parecida com JavaScript, mas as funções de regras de segurança são escritas em uma linguagem de programação específica de domínio com algumas limitações importantes:

  • As funções podem conter apenas uma única instrução return. Elas não podem conter nenhuma lógica adicional. Por exemplo, as funções não podem criar variáveis intermediárias, executar loops ou chamar serviços externos.
  • As funções podem acessar automaticamente funções e variáveis do escopo em que são definidas. Por exemplo, uma função definida no escopo service cloud.firestore tem acesso à variável resource e a funções integradas, como get() e exists().
  • Elas podem chamar outras funções, mas não são executadas novamente. A profundidade total da pilha de chamadas é limitada a 20.

Uma função é definida com a palavra-chave function e pode utilizar argumentos ou não. Por exemplo, pode ser necessário combinar os dois tipos de condição usados nos exemplos acima em uma única função:

service cloud.firestore {
  match /databases/{database}/documents {
    // 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 /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

O uso de funções nas regras de segurança as torna mais fáceis de atualizar à medida que a complexidade delas aumenta.

Realtime Database

Conforme descrito acima, as regras do Realtime Database incluem três elementos básicos: o local do banco de dados como um espelho da estrutura JSON do banco de dados, o tipo de solicitação e a condição que concederá acesso.

Local do banco de dados

A estrutura das regras precisa seguir a estrutura dos dados que você armazenou no banco. Por exemplo, em um aplicativo de bate-papo com uma lista de mensagens, é possível ter dados como estes:

  {
    "messages": {
      "message0": {
        "content": "Hello",
        "timestamp": 1405704370369
      },
      "message1": {
        "content": "Goodbye",
        "timestamp": 1405704395231
      },
      ...
    }
  }

Suas regras precisam espelhar essa estrutura. Por exemplo:

  {
    "rules": {
      "messages": {
        "$message": {
          // only messages from the last ten minutes can be read
          ".read": "data.child('timestamp').val() > (now - 600000)",

          // new messages must have a string content and a number timestamp
          ".validate": "newData.hasChildren(['content', 'timestamp']) &&
                        newData.child('content').isString() &&
                        newData.child('timestamp').isNumber()"
        }
      }
    }
  }

Conforme o exemplo acima, as regras do Realtime Database são compatíveis com uma variável $location para corresponder os segmentos de caminho. Use o prefixo $ na frente do seu segmento de caminho para corresponder sua regra a qualquer nó filho no caminho.

  {
    "rules": {
      "rooms": {
        // This rule applies to any child of /rooms/, the key for each room id
        // is stored inside $room_id variable for reference
        "$room_id": {
          "topic": {
            // The room's topic can be changed if the room id has "public" in it
            ".write": "$room_id.contains('public')"
          }
        }
      }
    }
  }

Também é possível usar a $variable em paralelo com nomes de caminho constantes.

  {
    "rules": {
      "widget": {
        // a widget can have a title or color attribute
        "title": { ".validate": true },
        "color": { ".validate": true },

        // but no other child paths are allowed
        // in this case, $other means any key excluding "title" and "color"
        "$other": { ".validate": false }
      }
    }
  }

Método

No Realtime Database, existem três tipos de regra. Os tipos read e write aplicam-se ao método de uma solicitação recebida. O tipo validate aplica estruturas de dados e valida o formato e o conteúdo deles. As regras executam regras .validate depois de verificar se .write concedeu acesso.

Tipos de regra
.read Descreve se e quando os dados podem ser lidos pelos usuários.
.write Descreve se e quando os dados podem ser gravados.
.validate Define a formatação correta do valor, o tipo de dados e se o valor tem atributos filhos.

Por padrão, o acesso a um caminho será negado se não houver uma regra que permita esse acesso.

Condições de criação

Cloud Firestore

Uma condição é uma expressão booleana que determina se uma operação específica deve ser permitida ou negada. As variáveis request e resource fornecem contexto para essas condições.

A variável request

A variável request inclui os seguintes campos e informações correspondentes:

request.auth

Um JSON Web Token (JWT) que contém credenciais de autenticação do Firebase Authentication. O token auth contém um conjunto de declarações padrão e qualquer reivindicação personalizada criada por meio desse produto. Saiba mais sobre as regras de segurança do Firebase e o Firebase Authentication.

request.method

O request.method pode ser qualquer um dos métodos padrão ou um personalizado. Os métodos de conveniência read e write também existem para simplificar as regras de gravação que se aplicam a todos os métodos padrão somente leitura ou somente gravação, respectivamente.

request.params

Os request.params incluem quaisquer dados não relacionados especificamente com o request.resource que possam ser úteis para avaliação. Na prática, esse mapa precisa estar vazio para todos os métodos padrão e conter dados que não sejam recursos para métodos personalizados. É necessário cuidado para que os serviços não renomeiem nem modifiquem o tipo de qualquer chave ou valor apresentados como parâmetros.

request.path

O request.path é o caminho para o resource de destino. O caminho é relativo ao serviço. Os segmentos de caminho que contém caracteres seguros sem uso do URL, como /, são codificados em URL.

A variável resource

O resource é o valor atual dentro do serviço representado como um mapa de pares de chave-valor. A referência de resource em uma condição resultará em, no máximo, uma leitura do valor do serviço. Essa consulta contará em qualquer cota relacionada ao serviço do recurso. No caso de solicitações get, o resource será contabilizado somente na cota quando houver negação.

Operadores e precedência do operador

Use a tabela abaixo como referência para os operadores e a precedência correspondente deles nas regras do Cloud Firestore e do Storage.

Operadores: expressões arbitrárias a e b, campo f e índice i.

Operador Descrição Associatividade
a[i] a() a.f Índice, chamada, acesso ao campo da esquerda para a direita
!a -a Negação unária da direita para a esquerda
a/b a%b a*b Operadores multiplicativos da esquerda para a direita
a+b a-b Operadores aditivos da esquerda para a direita
a>b a>=b a<b a<=b Operadores relacionais da esquerda para a direita
a in b, a is b Existência em lista ou mapa, tipo de comparação da esquerda para a direita
a==b a!=b Operadores de comparação da esquerda para a direita
a && b Condicional E da esquerda para a direita
a || b Condicional OU da esquerda para a direita

Cloud Storage

Uma condição é uma expressão booleana que determina se uma operação específica deve ser permitida ou negada. As variáveis request e resource fornecem contexto para essas condições.

A variável request

A variável request inclui os seguintes campos e informações correspondentes:

request.auth

Um JSON Web Token (JWT) que contém credenciais de autenticação do Firebase Authentication. O token auth contém um conjunto de declarações padrão e qualquer reivindicação personalizada criada por meio desse produto. Saiba mais sobre as regras de segurança do Firebase e o Firebase Authentication.

request.method

O request.method pode ser qualquer um dos métodos padrão ou um personalizado. Os métodos de conveniência read e write também existem para simplificar as regras de gravação que se aplicam a todos os métodos padrão somente leitura ou somente gravação, respectivamente.

request.params

Os request.params incluem quaisquer dados não relacionados especificamente com o request.resource que possam ser úteis para avaliação. Na prática, esse mapa precisa estar vazio para todos os métodos padrão e conter dados que não sejam recursos para métodos personalizados. É necessário cuidado para que os serviços não renomeiem nem modifiquem o tipo de qualquer chave ou valor apresentados como parâmetros.

request.path

O request.path é o caminho para o resource de destino. O caminho é relativo ao serviço. Os segmentos de caminho que contém caracteres seguros sem uso do URL, como /, são codificados em URL.

A variável resource

O resource é o valor atual dentro do serviço representado como um mapa de pares de chave-valor. A referência de resource em uma condição resultará em, no máximo, uma leitura do valor do serviço. Essa consulta contará em qualquer cota relacionada ao serviço do recurso. No caso de solicitações get, o resource será contabilizado somente na cota quando houver negação.

Operadores e precedência do operador

Use a tabela abaixo como referência para os operadores e a precedência correspondente deles nas regras do Cloud Firestore e do Storage.

Operadores: expressões arbitrárias a e b, campo f e índice i.

Operador Descrição Associatividade
a[i] a() a.f Índice, chamada, acesso ao campo da esquerda para a direita
!a -a Negação unária da direita para a esquerda
a/b a%b a*b Operadores multiplicativos da esquerda para a direita
a+b a-b Operadores aditivos da esquerda para a direita
a>b a>=b a<b a<=b Operadores relacionais da esquerda para a direita
a in b, a is b Existência em lista ou mapa, tipo de comparação da esquerda para a direita
a==b a!=b Operadores de comparação da esquerda para a direita
a && b Condicional E da esquerda para a direita
a || b Condicional OU da esquerda para a direita

Realtime Database

Uma condição é uma expressão booleana que determina se uma operação específica deve ser permitida ou negada. É possível definir essas condições nas regras do Realtime Database das seguintes maneiras.

Variáveis predefinidas

Há diversas variáveis úteis e predefinidas que podem ser acessadas dentro de uma definição de regras. Veja um breve resumo de cada uma:

Variáveis predefinidas
now O horário atual em milissegundos desde a era Linux. Isso funciona muito bem para validar carimbos de data/hora criados com o firebase.database.ServerValue.TIMESTAMP do SDK.
root Um RuleDataSnapshot que representa o caminho raiz no banco de dados do Firebase como ele existia antes da tentativa de operação.
newData Um RuleDataSnapshot que representa os dados como eles existiriam após a tentativa de operação. Inclui os novos dados que estão sendo gravados e dados existentes.
data Um RuleDataSnapshot que representa os dados como eles existiam antes da tentativa de operação.
$ variables Um caminho curinga usado para representar códigos e chaves filhas dinâmicas.
auth Representa o payload do token de um usuário autenticado.

Essas variáveis podem ser usadas em qualquer lugar nas suas regras. Por exemplo, as regras de segurança abaixo garantem que os dados gravados no nó /foo/ sejam strings com menos de 100 caracteres:

{
  "rules": {
    "foo": {
      // /foo is readable by the world
      ".read": true,

      // /foo is writable by the world
      ".write": true,

      // data written to /foo must be a string less than 100 characters
      ".validate": "newData.isString() && newData.val().length < 100"
    }
  }
}

Regras com base em dados

Todos os dados no seu banco podem ser usados nas regras. Utilizando as variáveis predefinidas root, data e newData, é possível acessar qualquer caminho da forma como ele existiria antes ou depois de um evento de gravação.

Veja este exemplo, que permite operações de gravação contanto que o valor do nó /allow_writes/ seja true, o nó pai não tenha uma sinalização readOnly e haja um filho chamado foo nos dados recém-gravados:

".write": "root.child('allow_writes').val() === true &&
          !data.parent().child('readOnly').exists() &&
          newData.child('foo').exists()"

Regras com base em consultas

Apesar de não ser possível usar regras como filtros, há a opção de limitar o acesso a subconjuntos de dados por meio de parâmetros de consulta nas regras. Use as expressões query. nas suas regras para conceder acesso de leitura ou de gravação com base nos parâmetros de consulta.

Por exemplo, a seguinte regra com base em consultas usa regras de segurança com base em usuários e regras com base em consultas para restringir o acesso a dados no conjunto baskets somente aos carrinhos de compra do usuário ativo:

"baskets": {
  ".read": "auth.uid != null &&
            query.orderByChild == 'owner' &&
            query.equalTo == auth.uid" // restrict basket access to owner of basket
}

A seguinte consulta, que inclui os parâmetros de consulta na regra, seria bem-sucedida:

db.ref("baskets").orderByChild("owner")
                 .equalTo(auth.currentUser.uid)
                 .on("value", cb)                 // Would succeed

No entanto, as consultas que não incluem os parâmetros na regra falhariam e mostrariam um erro PermissionDenied:

db.ref("baskets").on("value", cb)                 // Would fail with PermissionDenied

Você também pode usar regras baseadas em consulta para limitar a quantidade de dados que um cliente baixa por meio das operações de leitura.

Por exemplo, a seguinte regra limita o acesso de leitura somente aos primeiros 1.000 resultados de uma consulta, ordenados por prioridade:

messages: {
  ".read": "query.orderByKey &&
            query.limitToFirst <= 1000"
}

// Example queries:

db.ref("messages").on("value", cb)                // Would fail with PermissionDenied

db.ref("messages").limitToFirst(1000)
                  .on("value", cb)                // Would succeed (default order by key)

As expressões query. a seguir estão disponíveis nas regras do Realtime Database.

Expressões de regra com base em consultas
Expressão Tipo Descrição
query.orderByKey
query.orderByPriority
query.orderByValue
booleano Verdadeiro para consultas ordenadas por chave, prioridade ou valor. Falso, em outros casos.
query.orderByChild string
nulo
Usa uma string para representar o caminho relativo para um nó filho. Por exemplo, query.orderByChild == "address/zip". Se a consulta não for ordenada por um nó filho, esse valor é nulo.
query.startAt
query.endAt
query.equalTo
string
número
booleano
nulo
Recupera os limites da consulta em execução ou, se não houver limite definido, retorna nulo.
query.limitToFirst
query.limitToLast
número
nulo
Recupera o limite na consulta em execução ou, se não houver limite definido, retorna nulo.

Operadores

As regras do Realtime Database são compatíveis com um número de operadores que podem ser usados para combinar variáveis na instrução de condição. Veja a lista completa de operadores na documentação de referência.

Como criar condições

Suas condições reais variam de acordo com o acesso que você quer conceder. As regras oferecem intencionalmente um grau enorme de flexibilidade, de modo que as regras do seu aplicativo possam ser tão simples ou complexas quanto for necessário.

Para saber mais sobre como criar regras simples e prontas para produção, consulte Regras básicas de segurança.