As Firebase Security Rules para Cloud Storage são usadas para determinar quem tem acesso de leitura e gravação
aos arquivos armazenados no Cloud Storage, além de como os arquivos são estruturados
e quais metadados elas contêm. Cloud Storage Security Rules são compostas de regras que
considere a request
e a resource
para permitir ou negar uma ação desejada, como
como fazer upload de um arquivo ou recuperar metadados de arquivos. Estes documentos de referência abrangem
os tipos de regras, as propriedades de uma request
e uma resource
, os dados
tipos usados por Cloud Storage Security Rules e como os erros ocorrem.
Regra
Um rule
é uma expressão que é avaliada para determinar se um request
é
para realizar uma ação desejada.
Tipos
Allow
As regras allow
consistem em um método, como read
ou write
, bem como
uma condição opcional. Quando uma regra é executada, a condição é avaliada
Se a condição for avaliada como true
, o método desejado será permitido. caso contrário,
o método é negado. Uma regra allow
sem condição sempre permite a
o método desejado.
// Always allow method allow <method>; // Allow method if condition is true allow <method>: if <condition>;
Atualmente, allow
é o único tipo de regra aceito.
Métodos de solicitação
Ler
O método read
abrange todas as solicitações em que são lidos dados ou metadados de arquivos.
incluindo downloads de arquivos e leituras de metadados de arquivos.
// Always allow reads allow read; // Allow reads if condition evaluates to true allow read: if <condition>;
Gravação
O método write
abrange todas as solicitações em que os dados ou metadados de arquivos são gravados.
incluindo uploads, exclusões e atualizações de metadados de arquivos.
// Always allow writes allow write; // Allow writes if condition evaluates to true allow write: if <condition>;
Correspondência
As regras são executadas quando um usuário request
(como um upload ou download de arquivo).
corresponde a um caminho de arquivo coberto por uma regra. Um match
consiste em um caminho e um corpo.
que deve conter pelo menos uma regra allow
. Se nenhum caminho corresponder, a solicitação
for rejeitada.
É possível usar match
em um caminho totalmente nomeado ou inserir caracteres curinga para corresponder a todos
caminhos que se encaixam em um determinado padrão.
Segmentos de caminho
single_segment
É possível usar segmentos de caminho único para criar uma regra que corresponda a um arquivo armazenado em Cloud Storage.
// Allow read at "path" if condition evaluates to true match /path { allow read: if <condition>; }
Vários segmentos de caminho e caminhos aninhados também são permitidos:
// Allow read at "path/to/object" if condition evaluates to true match /path { match /to { match /object { allow read: if <condition>; } } }
{single_segment_wildcard}
Se quiser aplicar uma regra a vários arquivos no mesmo caminho, use um
segmento de caminho curinga para corresponder a todos os arquivos em um determinado caminho. Uma variável curinga
é declarado em um caminho ao colocar uma variável entre chaves: {variable}
.
Essa variável pode ser acessada na instrução de correspondência como um string
.
// Allow read at any path "/*", if condition evaluates to true match /{single_path} { // Matches "path", "to", or "object" but not "path/to/object" allow read: if <condition>; }
Vários segmentos de caminho e caminhos aninhados também podem ter caracteres curinga:
// Allow read at any path "/path/*/newPath/*", if condition evaluates to true match /path/{first_wildcard} { match /newPath/{second_wildcard} { // Matches "path/to/newPath/newObject" or "path/from/newPath/oldObject" allow read: if <condition>; } }
{multi_segment_wildcard=**}
Se você quiser corresponder qualquer número de segmentos em um caminho ou abaixo dele, use um caractere curinga de vários segmentos, que corresponderá a todas as solicitações para e abaixo do o local. Isso pode ser útil para fornecer ao usuário seu próprio formato espaço de armazenamento ou criar regras que correspondam a muitos segmentos de caminho diferentes (como como criar um conjunto de arquivos publicamente legível ou exigir autenticação para todas as gravações).
Um caminho curinga com vários segmentos é declarado de maneira semelhante a um único segmento
curinga, com a adição de =**
no final da variável:
{variable=**}
. Uma variável curinga com vários segmentos está disponível na correspondência
instrução como um objeto path
.
// Allow read at any path "/**", if condition evaluates to true match /{multi_path=**} { // Matches anything at or below this, from "path", "path/to", "path/to/object", ... allow read: if <condition>; }
Solicitação
A variável request
é fornecida dentro de uma condição para representar o
que está sendo feita nesse caminho. A variável request
tem vários
que podem ser usadas para decidir se a solicitação de entrada será permitida.
Propriedades
auth
Quando um usuário autenticado faz uma solicitação em Cloud Storage,
a variável auth
é preenchida com o uid
do usuário (request.auth.uid
) conforme
bem como as declarações do JWT Firebase Authentication (request.auth.token
).
request.auth.token
contém algumas ou todas as chaves a seguir:
Campo | Descrição |
---|---|
email |
O endereço de e-mail associado à conta, se essa informação existir. |
email_verified |
true se o usuário tiver verificado que tem acesso ao endereço email . Alguns provedores verificam automaticamente esses endereços de e-mail. |
phone_number |
O número de telefone associado à conta, se essa informação existir. |
name |
O nome de exibição do usuário, se ele tiver sido definido. |
sub |
O UID do Firebase do usuário. Ele é exclusivo dentro de um projeto. |
firebase.identities |
O dicionário de todas as identidades associadas à conta desse usuário. As chaves do dicionário podem ser qualquer uma das seguintes: email , phone , google.com , facebook.com , github.com , twitter.com . Os valores do dicionário são matrizes de identificadores exclusivos de cada provedor de identidade associado à conta. Por exemplo, auth.token.firebase.identities["google.com"][0] contém o primeiro ID de usuário do Google associado à conta. |
firebase.sign_in_provider |
O provedor de entrada usado para receber esse token. Pode ser uma das seguintes strings: custom , password , phone , anonymous , google.com , facebook.com , github.com ou twitter.com . |
firebase.tenant |
O ID do locatário associado à conta, se houver. Por exemplo, tenant2-m6tyz . |
Se você estiver usando a autenticação personalizada, request.auth.token
também conterá qualquer
reivindicações especificadas pelo desenvolvedor.
Quando um usuário não autenticado realiza uma solicitação, request.auth
é null
.
// Allow requests from authenticated users allow read, write: if request.auth != null;
path
A variável path
contém o caminho que uma request
está sendo executada.
contra.
// Allow a request if the first path segment equals "images" allow read, write: if request.path[0] == 'images';
resource
A variável resource
contém os metadados de um arquivo que está sendo enviado ou o
metadados atualizados de um arquivo existente. Isso está relacionado à
A variável resource
, que contém os metadados do arquivo atuais em
o caminho solicitado, em vez dos novos metadados.
// Allow a request if the new value is smaller than 5MB allow read, write: if request.resource.size < 5 * 1024 * 1024;
request.resource
contém as seguintes propriedades de resource
:
Propriedade |
---|
name |
bucket |
metadata |
size |
contentType |
time
A variável time
contém um carimbo de data/hora que representa o horário atual do servidor
em que uma solicitação está sendo avaliada. Use isso para fornecer acesso com base no tempo
a arquivos, como: permitir apenas o upload de arquivos até uma determinada data;
ou permitir que os arquivos sejam lidos até uma hora após o upload.
// Allow a read if the file was created less than one hour ago allow read: if request.time < resource.timeCreated + duration.value(1, 'h');
Muitas funções são fornecidas para gravar regras usando carimbos de data/hora e durations.
Recurso
A variável resource
contém metadados para arquivos em
Cloud Storage, como nome, tamanho, hora de criação do arquivo e
metadados personalizados.
Propriedades
name
String com o nome completo do arquivo, incluindo o caminho para ele.
// Allow reads if the resource name is "path/to/object" allow read: if resource.name == 'path/to/object'
bucket
Uma string contendo o Google Cloud Storage no bucket em que esse arquivo está armazenado.
// Allow reads of all resources in your bucket allow read: if resource.bucket == '<your-cloud-storage-bucket>'
generation
Um inteiro que contém o arquivo do Google Cloud Storage geração de objetos do o arquivo. Usado para controle de versão de objetos.
// Allow reads if the resource matches a known object version allow read: if resource.generation == <known-generation>
metageneration
Um inteiro que contém o arquivo do Google Cloud Storage metageração de objeto do arquivo. Usado para controle de versão de objetos.
// Allow reads if the resource matches a known object metadata version allow read: if resource.metageneration == <known-generation>
size
Um inteiro contendo o tamanho do arquivo em bytes.
// Allow reads if the resource is less than 10 MB allow read: if resource.size < 10 * 1024 * 1024;
timeCreated
Um carimbo de data/hora que representa quando o arquivo foi criado.
// Allow reads if the resource was created less than an hour ago allow read: if resource.timeCreated < request.time + duration.value(60, "m")
updated
Carimbo de data/hora que representa quando o arquivo foi atualizado pela última vez.
// Allow reads if the resource was updated less than an hour ago allow read: if resource.updated < request.time + duration.value(60, "m")
md5Hash
Uma string contendo o hash MD5 do .
// Allow writes if the hash of the uploaded file is the same as the existing file allow write: if request.resource.md5Hash == resource.md5Hash;
crc32c
Uma string contendo o crc32c hash do .
// Allow writes if the hash of the uploaded file is the same as the existing file allow write: if request.resource.crc32c == resource.crc32c;
etag
Uma string que contém a etag do .
// Allow writes if the etag matches a known object etag allow write: if resource.etag == <known-generation>
contentDisposition
String com a disposição de conteúdo do arquivo.
// Allow reads if the content disposition matches a certain value allow read: if resource.contentDisposition == 'inlined';
contentEncoding
String com a codificação de conteúdo do arquivo.
// Allow reads if the content is encoded with gzip allow read: if resource.contentEncoding == 'gzip';
contentLanguage
String com o idioma do conteúdo do arquivo.
// Allow reads if the content language is Japanese allow read: if resource.contentLanguage == 'ja';
contentType
String com o tipo de conteúdo do arquivo.
// Allow reads if the content type is PNG. allow read: if resource.contentType == 'image/png';
metadata
Um Map<String, String>
contendo metadados adicionais fornecidos pelo desenvolvedor
campos.
// Allow reads if a certain metadata field matches a desired value allow read: if resource.metadata.customProperty == 'customValue';
firestore.get e firestore.exists
As funções firestore.get()
e firestore.exists()
permitem que você acesse
documentos em Cloud Firestore para avaliar critérios de autorização complexos.
As funções firestore.get()
e firestore.exists()
esperam
caminhos de documento totalmente especificados. Ao usar variáveis para criar caminhos para
firestore.get()
e firestore.exists()
, você precisa fazer o escape explícito
variáveis usando a sintaxe $(variable)
.
firestore.get
Recebe o conteúdo de um documento Cloud Firestore.
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.uid)).data.memberships } } }
firestore.exists
Verifique se existe um documento Cloud Firestore.
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.uid)) } } }
Serviço
O service
é a primeira declaração em um arquivo Cloud Storage Security Rules.
especifica a qual serviço essas regras serão aplicadas.
Nome
name
O nome das regras de serviço a que as regras de serviço serão aplicadas. O único valor atual é
firebase.storage
:
// Specify the service name service firebase.storage { match /b/{bucket}/o { ... } }
Tipos de dados
O idioma Rules permite verificar o tipo usando o operador is
.
// For example
a is null
a is string
null
O tipo de dados null
representa um valor que não existe.
allow read: if request.auth != null;
bool
O tipo bool
representa um valor booleano true
ou false
.
allow read: if true; // always succeeds allow write: if false; // always fails
Comparação
Os valores booleanos podem ser comparados usando os operadores ==
!=
.
Operações booleanas
Operação | Expressão |
---|---|
AND |
x && y |
OR |
x || y |
NOT |
!x |
As operações causam um curto-circuito e podem retornar true
, false
ou uma
Erro.
allow read: if true || false; // always succeeds, short circuits at true allow write: if false && true; // always fails, short circuits at false
int
e float
Os tipos int
e float
representam números. Ints são: 0
, 1
, -2
etc.
, enquanto os pontos flutuantes são: 1.0
, -2.0
, 3.33
etc.
Ints são valores assinados de 64 bits e os pontos flutuantes são valores compatíveis com IEEE 754 de 64 bits.
Valores do tipo int
serão forçados para float
quando usados em comparações e
operações aritméticas com um valor float
.
Comparação
Ints e pontos flutuantes podem ser comparados e ordenados usando ==
, !=
, >
, <
,
operadores >=
e <=
.
Aritmética
Ints e pontos flutuantes podem ser adicionados, subtraídos, multiplicados, divididos, modulados e negado:
Operação | Expressão |
---|---|
Adição | x + y |
Subtração | x - y |
Multiplicação | x * y |
Divisão | x / y |
Módulo | x % y |
Negação | -x |
Funções matemáticas
O Firebase Security Rules para Cloud Storage também oferece vários assistentes de matemática para simplificar expressões:
Função | Descrição |
---|---|
math.ceil(x) |
Limite do valor numérico |
math.floor(x) |
Valor mínimo do valor numérico |
math.round(x) |
Arredondar o valor de entrada para o int mais próximo |
math.abs(x) |
Valor absoluto da entrada |
math.isInfinite(x) |
Teste se o valor é ±∞ e retorna um bool . |
math.isNaN(x) |
Teste se o valor não é um número NaN , retorna um bool |
string
Comparação
Strings podem ser comparadas e ordenadas lexograficamente usando ==
, !=
, >
, <
, >=
e
Operadores <=
.
Concatenação
Strings podem ser concatenadas usando o operador +
.
// Concatenate a file name and extension 'file' + '.txt'
Índice e intervalo
O operador index
, string[]
, retorna uma string que contém o caractere
no índice fornecido na string.
// Allow reads of files that begin with 'a' match /{fileName} { allow read: if fileName[0] == 'a'; }
O operador range
, string[i:j]
, retorna uma string que contém o
caracteres entre os índices especificados, de i
(inclusive) até j
(exclusivo). Se i
ou j
não forem especificados, o padrão será 0 e o tamanho do
a string, respectivamente, mas pelo menos i
ou j
precisam ser especificados
para que o intervalo seja válido.
// Allow reads of files that begin with 'abcdef' match /{fileName} { allow read: if fileName[0:6] == 'abcdef'; }
Os operadores index
e range
resultarão em erro se os índices fornecidos
excedem os limites de string.
size
Retorna o número de caracteres na string.
// Allow files with names less than 10 characters match /{fileName} { allow write: if fileName.size() < 10; }
matches
Executa uma correspondência de expressão regular, retorna true
se a string corresponder ao
usando uma determinada expressão regular. Usos
Sintaxe do Google RE2.
// Allow writes to files which end in ".txt" match /{fileName} { allow write: if fileName.matches('.*\\.txt') }
split
divide uma string de acordo com uma expressão regular fornecida e retorna um list
.
de strings. Usa a sintaxe do Google RE2.
// Allow files named "file.*" to be uploaded match /{fileName} { allow write: if fileName.split('.*\\..*')[0] == 'file' }
path
Os caminhos são nomes semelhantes a diretórios com correspondência de padrão opcional. A
A presença de uma barra /
indica o início de um segmento de caminho.
path
Converte um argumento string
em um path
.
// Allow reads on a specific file path match /{allFiles=**} { allow read: if allFiles == path('/path/to/file'); }
timestamp
Os carimbos de data/hora estão em UTC, com valores possíveis começando em 0001-01-01T00.00.00Z e termina em 9999-12-31T23.59.59Z.
Comparação
Os carimbos de data/hora podem ser comparados e ordenados usando ==
, !=
, >
, <
, >=
e
Operadores <=
.
Aritmética
Os carimbos de data/hora são compatíveis com adição e subtração entre carimbos de data/hora e durações, como da seguinte forma:
Expressão | Resultado |
---|---|
timestamp + duration |
timestamp |
duration + timestamp |
timestamp |
timestamp - duration |
timestamp |
timestamp - timestamp |
duration |
duration + duration |
duration |
duration - duration |
duration |
date
Um valor timestamp
contendo apenas year
, month
e day
.
// Allow reads on the same day that the resource was created. allow read: if request.time.date() == resource.timeCreated.date()
year
O valor do ano em formato inteiro, de 1 a 9.999.
// Allow reads on all requests made before 2017 allow read: if request.time.year() < 2017
month
O valor do mês como um inteiro, de 1 a 12.
// Allow reads on all requests made during the month of January allow read: if request.time.month() == 1;
day
O dia atual do mês como um inteiro, de 1 a 31.
// Allow reads on all requests made during the first day of each month allow read: if request.time.day() == 1;
time
Um valor duration
contendo a hora atual.
// Allow reads on all requests made before 12PM allow read: if request.time.time() < duration.time(12, 0, 0, 0);
hours
O valor das horas como um inteiro, de 0 a 23.
// Allow reads on all requests made before 12PM allow read: if request.time.hours() < 12;
minutes
O valor dos minutos como um inteiro, de 0 a 59.
// Allow reads during even minutes of every hour allow read: if request.time.minutes() % 2 == 0;
seconds
O valor dos segundos como um inteiro, de 0 a 59.
// Allow reads during the second half of each minute allow read: if request.time.seconds() > 29;
nanos
A fração de segundos, em nanos, como um inteiro.
// Allow reads during the first 0.1 seconds of each second allow read: if request.time.nanos() < 100000000;
dayOfWeek
O dia da semana, de 1 (segunda-feira) a 7 (domingo).
// Allow reads on weekdays (Monday to Friday) allow read: if request.time.dayOfWeek() < 6;
dayOfYear
O dia do ano atual, de 1 a 366.
// Allow reads every fourth day allow read: if request.time.dayOfYear() % 4 == 0;
toMillis
Retorna o número atual de milissegundos desde a época do Unix.
// Allow reads if the request is made before a specified time allow read: if request.time.toMillis() < <milliseconds>;
duration
Os valores de duração são representados como segundos mais segundos fracionários em nanossegundos.
Comparação
As durações podem ser comparadas e ordenadas usando ==
, !=
, >
, <
, >=
e
Operadores <=
.
Aritmética
As durações são compatíveis com adição e subtração entre carimbos de data/hora e durações, como da seguinte forma:
Expressão | Resultado |
---|---|
timestamp + duration |
timestamp |
duration + timestamp |
timestamp |
timestamp - duration |
timestamp |
timestamp - timestamp |
duration |
duration + duration |
duration |
duration - duration |
duration |
seconds
O número de segundos na duração atual. Precisa ser entre -315.576.000.000 e +315.576.000.000, inclusive.
nanos
O número de frações de segundos (em nanossegundos) da duração atual. Deve entre -999.999.999 e +999.999.999. Para segundos diferentes de zero e diferentes de zero nanonsegundos, os sinais de ambos devem estar de acordo.
duration.value
As durações podem ser criadas usando o duration.value(int magnitude, string units)
, que cria uma duração de tempo com base na magnitude e unidade fornecidas.
// All of these durations represent one hour: duration.value(1, "h") duration.value(60, "m") duration.value(3600, "s")
Os unit
s possíveis são:
Duração | unit |
---|---|
Semanas | w |
Dias | d |
Horas | h |
Minutos | m |
Segundos | s |
Milissegundos | ms |
Nanossegundos | ns |
duration.time
As durações podem ser criadas usando o método
função duration.time(int hours, int minutes, int seconds, int nanoseconds)
,
que cria uma duração de horas, minutos, segundos e
nanossegundos.
// Create a four hour, three minute, two second, one nanosecond duration duration.time(4, 3, 2, 1)
list
Uma lista contém uma matriz ordenada de valores que pode ser do tipo: null
, bool
,
int
, float
, string
, path
, list
, map
, timestamp
ou duration
.
Dados x
e y
do tipo list
e i
e j
do tipo int
Criação
Para criar uma lista, adicione valores entre colchetes:
// Create a list of strings ['apples', 'grapes', 'bananas', 'cheese', 'goats']
Comparação
As listas podem ser comparadas usando os operadores ==
!=
. Igualdade de duas listas
exige que todos os valores sejam iguais.
Índice e intervalo
O operador index
, list[]
, retorna o item no índice fornecido na
lista.
// Allow reads of all files that begin with 'a' match /{fileName} { allow read: if fileName[0] == 'a'; }
O operador range
, list[i:j]
, retorna todos os itens em uma lista entre as
índices especificados, de i
(inclusivo) até j
(exclusivo). Se i
ou j
forem
não especificados, o padrão será 0 e o tamanho da lista, respectivamente, mas
pelo menos i
ou j
precisam ser especificados para que o intervalo seja válido.
// Allow reads of all files that begin with 'abcdef' match /{fileName} { allow read: if fileName[0:6] == 'abcdef'; }
in
Retorna true
se o valor pretendido estiver presente na lista ou false
se não estiver
presente.
// Allow read if a filename has the string 'txt' in it match /{fileName} { allow read: if 'txt' in fileName.split('\\.'); }
join
Combina uma lista de strings em uma única string separada por uma determinada.
// Allow reads if the joined array is 'file.txt' allow read: if ['file', 'txt'].join('.') == 'file.txt';
size
Número de itens na lista.
// Allow read if there are three items in our list allow read: if ['foo', 'bar', 'baz'].size() == 3;
hasAll
Retorna true
se todos os valores estiverem presentes na lista.
// Allow read if one list has all items in the other list allow read: if ['file', 'txt'].hasAll(['file', 'txt']);
map
Um mapa contém pares de chave-valor, em que as chaves são strings e os valores podem ser qualquer
de: null
, bool
, int
, float
, string
, path
, list
, map
,
timestamp
ou duration
.
Criação
Para criar um mapa, adicione pares de chave-valor entre chaves:
// Create a map of strings to strings { 'mercury': 'mars', 'rain': 'cloud', 'cats': 'dogs', }
Comparação
Os mapas podem ser comparados usando os operadores ==
!=
. Igualdade de dois mapas
requer que todas as chaves estejam presentes em ambos os mapas e que todos os valores sejam iguais.
Índice
Para acessar os valores em um mapa, use a notação de colchete ou ponto:
// Access custom metadata properties allow read: if resource.metadata.property == 'property' allow write: if resource.metadata['otherProperty'] == 'otherProperty'
Se não houver uma chave, um error
será retornado.
in
Retorna true
se a chave desejada estiver presente no mapa ou false
se não estiver
presente.
// Allow reads if a property is present in the custom metadata allow read: if property in resource.metadata;
size
O número de chaves no mapa.
// Allow reads if there's exactly one custom metadata key allow read: if resource.metadata.size() == 1;
keys
Uma lista de todas as chaves no mapa.
// Allow reads if the first metadata key is 'myKey' allow read: if resource.metadata.keys()[0] == 'myKey';
values
Uma lista de todos os valores no mapa, em ordem de chave.
// Allow reads if the first metadata value is 'myValue' allow read: if resource.metadata.values()[0] == 'myValue';
Erros
Avaliação de erros
Firebase Security Rules para Cloud Storage continua a avaliação quando são encontrados erros.
Isso é útil porque as expressões condicionais &&
e ||
podem absorver um erro
se a condicional entrar em curto-circuito para false
ou true
respectivamente. Por exemplo:
Expressão | Resultado |
---|---|
error && true |
error |
error && false |
false |
error || true |
true |
error || false |
error |
Locais comuns em que são gerados erros são: divisão por zero, acesso a valores em uma lista ou mapa que não existe e passar valores do tipo incorreto a uma função.
// Error if resource.size is zero allow read: if 1000000 / resource.size; // Error, key doesn't exist allow read: if resource.metadata.nonExistentKey == 'value'; // Error, no unit 'y' exists allow read: if request.time < resource.timeCreated + duration.value(1, 'y');