Este guia se baseia no aprendizado da sintaxe principal do guia de linguagem das regras de segurança do Firebase para mostrar como adicionar condições às regras de segurança do Firebase para Cloud Storage.
O principal alicerce 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 recebidos
Autenticação
As regras de segurança do Firebase para Cloud Storage integram-se ao Firebase Authentication para fornecer autenticação poderosa baseada no usuário para o Cloud Storage. Isso permite o controle de acesso granular com base nas 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 com as declarações do JWT do Firebase Authentication ( request.auth.token
).
Além disso, ao usar a autenticação personalizada, declarações adicionais aparecem no campo request.auth.token
.
Quando um usuário não autenticado realiza uma solicitação, a variável request.auth
é null
.
Usando esses dados, existem várias maneiras comuns de usar 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 caminhouid
- Grupo privado: verifique se as declarações do token personalizado correspondem 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 revelar dados públicos, como recursos de jogos, arquivos de som ou outros conteúdos estáticos.
// 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"); }
Privado autenticado
Em certos casos, você pode desejar que os dados possam ser visualizados por todos os usuários autenticados do 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 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 do request.auth
será fornecer aos 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 ID do grupo ou lista de
uid
autorizados) nos metadados do arquivo
Depois que esses dados forem armazenados no token ou nos metadados do arquivo, eles poderão ser referenciados dentro de 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 onde a solicitação está sendo executada, o horário em que a solicitação é recebida e o novo valor resource
se a solicitação é uma gravação.
O objeto 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 baseada no usuário dos documentos.
Uma lista completa de propriedades no objeto request
está disponível abaixo:
Propriedade | Tipo | 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 que 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 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 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.
As regras de segurança do Firebase para Cloud Storage fornecem metadados de arquivo no objeto resource
, que contém pares chave/valor dos metadados exibidos em um objeto do Cloud Storage. Essas propriedades podem ser inspecionadas em solicitações read
ou write
para garantir a integridade dos dados.
Em solicitações write
(como uploads, atualizações de metadados e exclusões), além do objeto resource
, que contém metadados de arquivo para o arquivo que existe atualmente no caminho da solicitação, você também tem a capacidade de 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 aplicativo, como tipo ou tamanho de arquivo.
Uma lista completa de propriedades no objeto resource
está disponível abaixo:
Propriedade | Tipo | Descrição |
---|---|---|
name | corda | O nome completo do objeto |
bucket | corda | O nome do bucket em que este objeto reside. |
generation | interno | A geração do objeto Google Cloud Storage deste objeto. |
metageneration | interno | A metageração de objeto do Google Cloud Storage deste objeto. |
size | interno | 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 | O etag associado a este objeto. |
contentDisposition | corda | A disposição do 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
.
Aprimore com o Cloud Firestore
Você pode acessar documentos no Cloud Firestore para avaliar outros critérios de autorização.
Usando as funções firestore.get()
e firestore.exists()
, suas regras de segurança podem avaliar solicitações recebidas em relação a documentos no Cloud Firestore. As funções firestore.get()
e firestore.exists()
esperam caminhos de documentos totalmente especificados. Ao usar variáveis para construir caminhos para firestore.get()
e firestore.exists()
, você precisa escapar explicitamente das variáveis usando a sintaxe $(variable)
.
No exemplo abaixo, vemos uma regra que restringe o acesso de leitura aos arquivos aos usuários que são membros de determinados clubes.
service firebase.storage { match /b/{bucket}/o { match /users/{club}/files/{fileId} { allow read: if club in firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships } } }No próximo exemplo, apenas os amigos de um usuário podem ver suas fotos.
service firebase.storage { match /b/{bucket}/o { match /users/{userId}/photos/{fileId} { allow read: if firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id)) } } }
Depois de criar e salvar suas primeiras regras de segurança do Cloud Storage que usam essas funções do Cloud Firestore, você será solicitado no console do Firebase ou na CLI do Firebase a ativar permissões para conectar os dois produtos.
Você pode desativar o recurso removendo uma função do IAM, conforme descrito em Gerenciar e implantar regras de segurança do Firebase .
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 do 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, você pode querer 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 JavaScript, mas as funções das regras de segurança do Firebase 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
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 estão definidas. Por exemplo, uma função definida no escopo do
service firebase.storage
tem acesso à variávelresource
e, somente para o Cloud Firestore, funções integradas, comoget()
eexists()
. - As funções podem chamar outras funções, mas não podem recorrer. A profundidade total da pilha de chamadas é limitada a 10.
- Na versão
rules2
, as funções podem definir variáveis usando a palavra-chavelet
. 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 aceita zero ou mais argumentos. Por exemplo, você pode querer combinar os dois tipos de condições usadas 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 torna-as mais fáceis de manter à medida que a complexidade das regras aumenta.
Próximos passos
Após esta discussão sobre as condições, você terá uma compreensão mais sofisticada das Regras e estará pronto para:
Aprenda como lidar com os principais casos de uso e conheça o fluxo de trabalho para desenvolver, testar e implantar regras:
- Escreva regras que abordem cenários comuns .
- Aumente seu conhecimento analisando situações em que você deve identificar e evitar regras inseguras .
- Teste regras usando o emulador do Cloud Storage e a biblioteca de testes de regras de segurança dedicada .
- Revise os métodos disponíveis para implantação de regras .