Condições de uso nas regras de segurança do Firebase Cloud Storage

Este guia baseia-se no aprendizado da sintaxe principal do guia de linguagem Firebase Security Rules para mostrar como adicionar condições às suas Firebase Security Rules for Cloud Storage.

O principal bloco de construção das Regras de segurança do Cloud Storage é a condição . Uma condição é uma expressão booleana que determina se uma determinada operação deve ser permitida ou negada. Para regras básicas, usar literais true e false como condições funciona perfeitamente bem. Mas a linguagem Firebase Security Rules for Cloud Storage oferece maneiras de escrever condições mais complexas que podem:

  • Verifique a autenticação do usuário
  • Validar dados de entrada

Autenticação

As regras de segurança do Firebase para Cloud Storage se integram ao Firebase Authentication para fornecer uma autenticação poderosa baseada no usuário ao Cloud Storage. Isso permite o controle de acesso granular com base em declarações de um token do Firebase Authentication.

Quando um usuário autenticado realiza uma solicitação no Cloud Storage, a variável request.auth é preenchida com o uid do usuário ( request.auth.uid ), bem como as declarações do JWT do Firebase Authentication ( request.auth.token ).

Além disso, ao usar a autenticação personalizada, declarações adicionais são exibidas no campo request.auth.token .

Quando um usuário não autenticado executa uma solicitação, a variável request.auth é null .

Usando esses dados, há várias maneiras comuns de usar a autenticação para proteger arquivos:

  • Público: ignore request.auth
  • Privado autenticado: verifique se request.auth não é null
  • Usuário privado: verifique se request.auth.uid é igual a um caminho uid
  • Grupo privado: verifique as declarações do token personalizado para corresponder a uma declaração escolhida ou leia os metadados do arquivo para ver se existe um campo de metadados

Público

Qualquer regra que não considere o contexto request.auth pode ser considerada uma regra public , pois não considera o contexto de autenticação do usuário. Essas regras podem ser úteis para exibir dados públicos, como ativos de jogos, arquivos de som ou outro conteúdo estático.

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

Autenticado privado

Em alguns casos, você pode querer que os dados sejam visualizados por todos os usuários autenticados de seu aplicativo, mas não por usuários não autenticados. Como a variável request.auth é null para todos os usuários não autenticados, tudo o que você precisa fazer é verificar se a variável request.auth existe para exigir autenticação:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

Usuário privado

De longe, o caso de uso mais comum para request.auth será fornecer a usuários individuais permissões granulares em seus arquivos: desde o upload de fotos de perfil até a leitura de documentos privados.

Como os arquivos no Cloud Storage têm um "caminho" completo para o arquivo, tudo o que é necessário para tornar um arquivo controlado por um usuário é uma informação exclusiva de identificação do usuário no prefixo do nome do arquivo (como o uid do usuário ) que pode ser verificada quando a regra é avaliada:

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth.uid == userId;
}

Grupo privado

Outro caso de uso igualmente comum será permitir permissões de grupo em um objeto, como permitir que vários membros da equipe colaborem em um documento compartilhado. Existem várias abordagens para fazer isso:

  • Crie um token personalizado do Firebase Authentication que contenha informações adicionais sobre um membro do grupo (como um ID do grupo)
  • Incluir informações do grupo (como um ID de grupo ou lista de uid autorizados) nos metadados do arquivo

Depois que esses dados são armazenados no token ou nos metadados do arquivo, eles podem ser referenciados em uma regra:

// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
  allow read: if resource.metadata.owner == request.auth.token.groupId;
  allow write: if request.auth.token.groupId == groupId;
}

Solicitar avaliação

Uploads, downloads, alterações de metadados e exclusões são avaliados usando a request enviada ao Cloud Storage. Além do ID exclusivo do usuário e da carga útil do Firebase Authentication no objeto request.auth , conforme descrito acima, a variável request contém o caminho do arquivo em que a solicitação está sendo executada, a hora em que a solicitação é recebida e o novo valor do resource , se o pedido é uma gravação. Cabeçalhos HTTP e estado de autenticação também estão incluídos.

O objeto de request também contém o ID exclusivo do usuário e a carga útil do Firebase Authentication no objeto request.auth , que será explicado mais detalhadamente na seção Segurança com base no usuário dos documentos.

Uma lista completa de propriedades no objeto de request está disponível abaixo:

Propriedade Modelo Descrição
auth mapa<string, string> Quando um usuário está conectado, fornece uid , o ID exclusivo do usuário e token , um mapa de declarações JWT do Firebase Authentication. Caso contrário, será null .
params mapa<string, string> Mapa contendo os parâmetros de consulta da solicitação.
path caminho Um path representa o caminho em que a solicitação está sendo executada.
resource mapa<string, string> O novo valor do recurso, presente apenas em solicitações de write .
time carimbo de data/hora Um carimbo de data/hora que representa a hora do servidor em que a solicitação é avaliada.

Avaliação de recursos

Ao avaliar as 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 que apenas arquivos com determinados tipos de conteúdo sejam carregados ou apenas arquivos maiores que um determinado tamanho sejam excluídos.

As regras de segurança do Firebase para Cloud Storage fornecem metadados de arquivo no objeto de resource , que contém pares de chave/valor dos metadados 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.

Em solicitações de write (como uploads, atualizações de metadados e exclusões), além do objeto de resource , que contém metadados de arquivo para o arquivo que existe atualmente no caminho da solicitação, você também pode usar o objeto request.resource , que contém um subconjunto dos metadados do arquivo a serem gravados se a gravação for permitida. Você pode usar esses dois valores para garantir a integridade dos dados ou impor restrições de aplicativos, como tipo ou tamanho de arquivo.

Uma lista completa de propriedades no objeto de resource está disponível abaixo:

Propriedade Modelo Descrição
name corda O nome completo do objeto
bucket corda O nome do bucket em que esse objeto reside.
generation int A geração do objeto do Google Cloud Storage deste objeto.
metageneration int A metageração do objeto do Google Cloud Storage deste objeto.
size int O tamanho do objeto em bytes.
timeCreated carimbo de data/hora Um carimbo de data/hora que representa a hora em que um objeto foi criado.
updated carimbo de data/hora Um carimbo de data/hora que representa a hora em que um objeto foi atualizado pela última vez.
md5Hash corda Um hash MD5 do objeto.
crc32c corda Um hash crc32c do objeto.
etag corda A etag associada a este objeto.
contentDisposition corda A disposição de conteúdo associada a este objeto.
contentEncoding corda A codificação de conteúdo associada a este objeto.
contentLanguage corda O idioma do conteúdo associado a este objeto.
contentType corda O tipo de conteúdo associado a este objeto.
metadata mapa<string, string> Pares de chave/valor de metadados personalizados adicionais especificados pelo desenvolvedor.

request.resource contém tudo isso com exceção de generation , metageneration , etag , timeCreated e updated .

Validar dados

As regras de segurança do Firebase para Cloud Storage também podem ser usadas para validação de dados, incluindo a validação de nome e caminho do arquivo, bem como propriedades de metadados de arquivo, como contentType e size .

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

Funções personalizadas

À medida que suas regras de segurança do Firebase se tornam mais complexas, convém agrupar conjuntos de condições em funções que podem ser reutilizadas em seu conjunto de regras. As regras de segurança suportam funções personalizadas. A sintaxe das funções personalizadas é um pouco parecida com a do JavaScript, mas as funções do Firebase Security Rules são escritas em uma linguagem específica do domínio que tem algumas limitações importantes:

  • As funções podem conter apenas uma única instrução de return . Eles não podem conter nenhuma lógica adicional. Por exemplo, eles não podem 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 do service firebase.storage tem acesso à variável de resource e, apenas para o Cloud Firestore, funções integradas, como get() e exists() .
  • As funções podem chamar outras funções, mas não podem ser recursivas. A profundidade total da pilha de chamadas é limitada a 10.
  • Nas regras de rules2 , as funções podem definir variáveis ​​usando a palavra-chave let . As funções podem ter qualquer número de ligações let, mas devem terminar com uma instrução return.

Uma função é definida com a palavra-chave function e recebe zero ou mais argumentos. Por exemplo, você pode querer combinar os dois tipos de condições usados ​​nos exemplos acima em uma única função:

service firebase.storage {
  match /b/{bucket}/o {
    // 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 /images/{imageId} {
      allow read, write: if signedInOrPublic();
    }
    match /mp3s/{mp3Ids} {
      allow read: if signedInOrPublic();
    }
  }
}

O uso de funções nas regras de segurança do Firebase as torna mais fáceis de manter à medida que a complexidade das regras aumenta.

Próximos passos

Após essa discussão sobre as condições, você terá uma compreensão mais sofisticada das Regras e estará pronto para:

Saiba como lidar com os principais casos de uso e conheça o fluxo de trabalho para desenvolver, testar e implantar regras:

,

Este guia baseia-se no aprendizado da sintaxe principal do guia de linguagem Firebase Security Rules para mostrar como adicionar condições às suas Firebase Security Rules for Cloud Storage.

O principal bloco de construção das Regras de segurança do Cloud Storage é a condição . Uma condição é uma expressão booleana que determina se uma determinada operação deve ser permitida ou negada. Para regras básicas, usar literais true e false como condições funciona perfeitamente bem. Mas a linguagem Firebase Security Rules for Cloud Storage oferece maneiras de escrever condições mais complexas que podem:

  • Verifique a autenticação do usuário
  • Validar dados de entrada

Autenticação

As regras de segurança do Firebase para Cloud Storage se integram ao Firebase Authentication para fornecer uma autenticação poderosa baseada no usuário ao Cloud Storage. Isso permite o controle de acesso granular com base em declarações de um token do Firebase Authentication.

Quando um usuário autenticado realiza uma solicitação no Cloud Storage, a variável request.auth é preenchida com o uid do usuário ( request.auth.uid ), bem como as declarações do JWT do Firebase Authentication ( request.auth.token ).

Além disso, ao usar a autenticação personalizada, declarações adicionais são exibidas no campo request.auth.token .

Quando um usuário não autenticado executa uma solicitação, a variável request.auth é null .

Usando esses dados, há várias maneiras comuns de usar a autenticação para proteger arquivos:

  • Público: ignore request.auth
  • Privado autenticado: verifique se request.auth não é null
  • Usuário privado: verifique se request.auth.uid é igual a um caminho uid
  • Grupo privado: verifique as declarações do token personalizado para corresponder a uma declaração escolhida ou leia os metadados do arquivo para ver se existe um campo de metadados

Público

Qualquer regra que não considere o contexto request.auth pode ser considerada uma regra public , pois não considera o contexto de autenticação do usuário. Essas regras podem ser úteis para exibir dados públicos, como ativos de jogos, arquivos de som ou outro conteúdo estático.

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

Autenticado privado

Em alguns casos, você pode querer que os dados sejam visualizados por todos os usuários autenticados de seu aplicativo, mas não por usuários não autenticados. Como a variável request.auth é null para todos os usuários não autenticados, tudo o que você precisa fazer é verificar se a variável request.auth existe para exigir autenticação:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

Usuário privado

De longe, o caso de uso mais comum para request.auth será fornecer a usuários individuais permissões granulares em seus arquivos: desde o upload de fotos de perfil até a leitura de documentos privados.

Como os arquivos no Cloud Storage têm um "caminho" completo para o arquivo, tudo o que é necessário para tornar um arquivo controlado por um usuário é uma informação exclusiva de identificação do usuário no prefixo do nome do arquivo (como o uid do usuário ) que pode ser verificada quando a regra é avaliada:

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth.uid == userId;
}

Grupo privado

Outro caso de uso igualmente comum será permitir permissões de grupo em um objeto, como permitir que vários membros da equipe colaborem em um documento compartilhado. Existem várias abordagens para fazer isso:

  • Crie um token personalizado do Firebase Authentication que contenha informações adicionais sobre um membro do grupo (como um ID do grupo)
  • Incluir informações do grupo (como um ID de grupo ou lista de uid autorizados) nos metadados do arquivo

Depois que esses dados são armazenados no token ou nos metadados do arquivo, eles podem ser referenciados em uma regra:

// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
  allow read: if resource.metadata.owner == request.auth.token.groupId;
  allow write: if request.auth.token.groupId == groupId;
}

Solicitar avaliação

Uploads, downloads, alterações de metadados e exclusões são avaliados usando a request enviada ao Cloud Storage. Além do ID exclusivo do usuário e da carga útil do Firebase Authentication no objeto request.auth , conforme descrito acima, a variável request contém o caminho do arquivo em que a solicitação está sendo executada, a hora em que a solicitação é recebida e o novo valor do resource , se o pedido é uma gravação. Cabeçalhos HTTP e estado de autenticação também estão incluídos.

O objeto de request também contém o ID exclusivo do usuário e a carga útil do Firebase Authentication no objeto request.auth , que será explicado mais detalhadamente na seção Segurança com base no usuário dos documentos.

Uma lista completa de propriedades no objeto de request está disponível abaixo:

Propriedade Modelo Descrição
auth mapa<string, string> Quando um usuário está conectado, fornece uid , o ID exclusivo do usuário e token , um mapa de declarações JWT do Firebase Authentication. Caso contrário, será null .
params mapa<string, string> Mapa contendo os parâmetros de consulta da solicitação.
path caminho Um path representa o caminho em que a solicitação está sendo executada.
resource mapa<string, string> O novo valor do recurso, presente apenas em solicitações de write .
time carimbo de data/hora Um carimbo de data/hora que representa a hora do servidor em que a solicitação é avaliada.

Avaliação de recursos

Ao avaliar as 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 que apenas arquivos com determinados tipos de conteúdo sejam carregados ou apenas arquivos maiores que um determinado tamanho sejam excluídos.

As regras de segurança do Firebase para Cloud Storage fornecem metadados de arquivo no objeto de resource , que contém pares de chave/valor dos metadados 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.

Em solicitações de write (como uploads, atualizações de metadados e exclusões), além do objeto de resource , que contém metadados de arquivo para o arquivo que existe atualmente no caminho da solicitação, você também pode usar o objeto request.resource , que contém um subconjunto dos metadados do arquivo a serem gravados se a gravação for permitida. Você pode usar esses dois valores para garantir a integridade dos dados ou impor restrições de aplicativos, como tipo ou tamanho de arquivo.

Uma lista completa de propriedades no objeto de resource está disponível abaixo:

Propriedade Modelo Descrição
name corda O nome completo do objeto
bucket corda O nome do bucket em que esse objeto reside.
generation int A geração do objeto do Google Cloud Storage deste objeto.
metageneration int A metageração do objeto do Google Cloud Storage deste objeto.
size int O tamanho do objeto em bytes.
timeCreated carimbo de data/hora Um carimbo de data/hora que representa a hora em que um objeto foi criado.
updated carimbo de data/hora Um carimbo de data/hora que representa a hora em que um objeto foi atualizado pela última vez.
md5Hash corda Um hash MD5 do objeto.
crc32c corda Um hash crc32c do objeto.
etag corda A etag associada a este objeto.
contentDisposition corda A disposição de conteúdo associada a este objeto.
contentEncoding corda A codificação de conteúdo associada a este objeto.
contentLanguage corda O idioma do conteúdo associado a este objeto.
contentType corda O tipo de conteúdo associado a este objeto.
metadata mapa<string, string> Pares de chave/valor de metadados personalizados adicionais especificados pelo desenvolvedor.

request.resource contém tudo isso com exceção de generation , metageneration , etag , timeCreated e updated .

Validar dados

As regras de segurança do Firebase para Cloud Storage também podem ser usadas para validação de dados, incluindo a validação de nome e caminho do arquivo, bem como propriedades de metadados de arquivo, como contentType e size .

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

Funções personalizadas

À medida que suas regras de segurança do Firebase se tornam mais complexas, convém agrupar conjuntos de condições em funções que podem ser reutilizadas em seu conjunto de regras. As regras de segurança suportam funções personalizadas. A sintaxe das funções personalizadas é um pouco parecida com a do JavaScript, mas as funções do Firebase Security Rules são escritas em uma linguagem específica do domínio que tem algumas limitações importantes:

  • As funções podem conter apenas uma única instrução de return . Eles não podem conter nenhuma lógica adicional. Por exemplo, eles não podem 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 do service firebase.storage tem acesso à variável de resource e, apenas para o Cloud Firestore, funções integradas, como get() e exists() .
  • As funções podem chamar outras funções, mas não podem ser recursivas. A profundidade total da pilha de chamadas é limitada a 10.
  • Nas regras de rules2 , as funções podem definir variáveis ​​usando a palavra-chave let . As funções podem ter qualquer número de ligações let, mas devem terminar com uma instrução return.

Uma função é definida com a palavra-chave function e recebe zero ou mais argumentos. Por exemplo, você pode querer combinar os dois tipos de condições usados ​​nos exemplos acima em uma única função:

service firebase.storage {
  match /b/{bucket}/o {
    // 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 /images/{imageId} {
      allow read, write: if signedInOrPublic();
    }
    match /mp3s/{mp3Ids} {
      allow read: if signedInOrPublic();
    }
  }
}

O uso de funções nas regras de segurança do Firebase as torna mais fáceis de manter à medida que a complexidade das regras aumenta.

Próximos passos

Após essa discussão sobre as condições, você terá uma compreensão mais sofisticada das Regras e estará pronto para:

Saiba como lidar com os principais casos de uso e conheça o fluxo de trabalho para desenvolver, testar e implantar regras: