Las reglas de seguridad de Firebase para Cloud Storage se utilizan para determinar quién tiene acceso de lectura y escritura a los archivos almacenados en Cloud Storage, además de cómo se estructuran los archivos y qué metadatos contienen. Las reglas de seguridad de Cloud Storage se componen de reglas que consideran la request
y el resource
para permitir o denegar una acción deseada, como cargar un archivo o recuperar los metadatos del archivo. Estos documentos de referencia cubren los tipos de reglas, las propiedades de una request
y un resource
, los tipos de datos que usan las reglas de seguridad de Cloud Storage y cómo se producen los errores.
Regla
Una rule
es una expresión que se evalúa para determinar si una request
puede realizar una acción deseada.
Tipos
Permitir
Las reglas de allow
constan de un método, como read
o write
, así como una condición opcional. Cuando se ejecuta una regla, se evalúa la condición y, si la condición se evalúa como true
, se permite el método deseado; de lo contrario, se deniega el método. Una regla de allow
sin condición siempre permite el método deseado.
// Always allow method allow <method>; // Allow method if condition is true allow <method>: if <condition>;
Actualmente, allow
es el único tipo de regla admitido.
Métodos de solicitud
Leer
El método de read
cubre todas las solicitudes en las que se leen datos o metadatos de archivos, incluidas las descargas de archivos y las lecturas de metadatos de archivos.
// Always allow reads allow read; // Allow reads if condition evaluates to true allow read: if <condition>;
Escribe
El método de write
cubre todas las solicitudes en las que se escriben datos o metadatos de archivos, incluidas las cargas de archivos, las eliminaciones de archivos y las actualizaciones de metadatos de archivos.
// Always allow writes allow write; // Allow writes if condition evaluates to true allow write: if <condition>;
Juego
Las reglas se ejecutan cuando una request
de usuario (como la carga o descarga de un archivo) coincide con una ruta de archivo cubierta por una regla. Una match
consta de una ruta y un cuerpo, que debe contener al menos una regla de allow
. Si no coincide ninguna ruta, se rechaza la solicitud.
Puede hacer match
una ruta con nombre completo o puede insertar comodines para hacer coincidir todas las rutas que se ajustan a un patrón determinado.
Segmentos de ruta
single_segment
Puede usar segmentos de ruta única para crear una regla que coincida con un archivo almacenado en Cloud Storage.
// Allow read at "path" if condition evaluates to true match /path { allow read: if <condition>; }
También se permiten varios segmentos de ruta y rutas anidadas:
// Allow read at "path/to/object" if condition evaluates to true match /path { match /to { match /object { allow read: if <condition>; } } }
{single_segment_wildcard}
Si desea aplicar una regla a varios archivos en la misma ruta, puede usar un segmento de ruta comodín para hacer coincidir todos los archivos en una ruta determinada. Una variable comodín se declara en una ruta envolviendo una variable entre llaves: {variable}
. Se puede acceder a esta variable dentro de la declaración de coincidencia como una 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>; }
Los segmentos de rutas múltiples y las rutas anidadas también pueden tener comodines:
// 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=**}
Si desea hacer coincidir cualquier número de segmentos de ruta en o debajo de una ruta, puede usar un comodín de varios segmentos, que coincidirá con todas las solicitudes hacia y debajo de la ubicación. Esto puede ser útil para proporcionar a un usuario su propio espacio de almacenamiento de forma libre o para crear reglas que coincidan con muchos segmentos de ruta diferentes (como crear un conjunto de archivos de lectura pública o requerir autenticación para todas las escrituras).
Una ruta comodín de varios segmentos se declara de manera similar a un comodín de un solo segmento, con la adición de =**
al final de la variable: {variable=**}
. Una variable comodín de varios segmentos está disponible dentro de la declaración de coincidencia como un objeto de 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>; }
Solicitud
La variable de request
se proporciona dentro de una condición para representar la solicitud que se realiza en esa ruta. La variable de request
tiene una serie de propiedades que se pueden usar para decidir si se permite la solicitud entrante.
Propiedades
auth
Cuando un usuario autenticado realiza una solicitud en Cloud Storage, la variable auth
se completa con el uid
del usuario ( request.auth.uid
), así como con los reclamos del JWT de autenticación de Firebase ( request.auth.token
).
request.auth.token
contiene algunas o todas las siguientes claves:
Campo | Descripción |
---|---|
email | La dirección de correo electrónico asociada con la cuenta, si está presente. |
email_verified | true si el usuario ha verificado que tiene acceso a la dirección de email . Algunos proveedores verifican automáticamente las direcciones de correo electrónico que poseen. |
phone_number | El número de teléfono asociado con la cuenta, si está presente. |
name | El nombre para mostrar del usuario, si está establecido. |
sub | El UID de Firebase del usuario. Esto es único dentro de un proyecto. |
firebase.identities | Diccionario de todas las identidades asociadas a la cuenta de este usuario. Las claves del diccionario pueden ser cualquiera de las siguientes: email , phone , google.com , facebook.com , github.com , twitter.com . Los valores del diccionario son matrices de identificadores únicos para cada proveedor de identidad asociado con la cuenta. Por ejemplo, auth.token.firebase.identities["google.com"][0] contiene el primer ID de usuario de Google asociado con la cuenta. |
firebase.sign_in_provider | El proveedor de inicio de sesión utilizado para obtener este token. Puede ser una de las siguientes cadenas: custom , password , phone , anonymous , google.com , facebook.com , github.com , twitter.com . |
firebase.tenant | TenantId asociado con la cuenta, si está presente. por ejemplo tenant2-m6tyz |
Si utiliza la autenticación personalizada, request.auth.token
también contiene las notificaciones personalizadas especificadas por el desarrollador.
Cuando un usuario no autenticado realiza una solicitud, request.auth
es null
.
// Allow requests from authenticated users allow read, write: if request.auth != null;
path
La variable de path
contiene la ruta en la que se realiza una request
.
// Allow a request if the first path segment equals "images" allow read, write: if request.path[0] == 'images';
resource
La variable de resource
contiene los metadatos de un archivo que se carga o los metadatos actualizados de un archivo existente. Esto está relacionado con la variable de resource
, que contiene los metadatos del archivo actual en la ruta solicitada, a diferencia de los metadatos nuevos.
// Allow a request if the new value is smaller than 5MB allow read, write: if request.resource.size < 5 * 1024 * 1024;
request.resource
contiene las siguientes propiedades de resource
:
Propiedad |
---|
name |
bucket |
metadata |
size |
contentType |
time
La variable de time
contiene una marca de tiempo que representa la hora actual del servidor en la que se evalúa una solicitud. Puede usar esto para proporcionar acceso basado en el tiempo a los archivos, como: solo permitir que los archivos se carguen hasta una fecha determinada, o solo permitir que los archivos se lean hasta una hora después de que se cargaron.
// Allow a read if the file was created less than one hour ago allow read: if request.time < resource.timeCreated + duration.value(1, 'h');
Se proporcionan muchas funciones para escribir reglas utilizando marcas de tiempo y duraciones .
Recurso
La variable de resource
contiene metadatos de archivo para archivos en Cloud Storage, como el nombre del archivo, el tamaño, la hora de creación y los metadatos personalizados.
Propiedades
name
Una cadena que contiene el nombre completo del archivo, incluida la ruta al archivo.
// Allow reads if the resource name is "path/to/object" allow read: if resource.name == 'path/to/object'
bucket
Una cadena que contiene el depósito de Google Cloud Storage en el que se almacena este archivo.
// Allow reads of all resources in your bucket allow read: if resource.bucket == '<your-cloud-storage-bucket>'
generation
Un int que contiene la generación de objetos de Google Cloud Storage del archivo. Se utiliza para el control de versiones de objetos.
// Allow reads if the resource matches a known object version allow read: if resource.generation == <known-generation>
metageneration
Un int que contiene la metageneración del objeto de Google Cloud Storage del archivo. Se utiliza para el control de versiones de objetos.
// Allow reads if the resource matches a known object metadata version allow read: if resource.metageneration == <known-generation>
size
Un int que contiene el tamaño del archivo en bytes.
// Allow reads if the resource is less than 10 MB allow read: if resource.size < 10 * 1024 * 1024;
timeCreated
Una marca de tiempo que representa cuándo se creó el archivo.
// Allow reads if the resource was created less than an hour ago allow read: if resource.timeCreated < request.time + duration.value(60, "m")
updated
Una marca de tiempo que representa cuándo se actualizó el archivo por ú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
Una cadena que contiene el hash MD5 del archivo.
// 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
Una cadena que contiene el hash crc32c del archivo.
// 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
Una cadena que contiene el etag del archivo.
// Allow writes if the etag matches a known object etag allow write: if resource.etag == <known-generation>
contentDisposition
Una cadena que contiene la disposición del contenido del archivo.
// Allow reads if the content disposition matches a certain value allow read: if resource.contentDisposition == 'inlined';
contentEncoding
Una cadena que contiene la codificación del contenido del archivo.
// Allow reads if the content is encoded with gzip allow read: if resource.contentEncoding == 'gzip';
contentLanguage
Una cadena que contiene el idioma del contenido del archivo.
// Allow reads if the content language is Japanese allow read: if resource.contentLanguage == 'ja';
contentType
Una cadena que contiene el tipo de contenido del archivo.
// Allow reads if the content type is PNG. allow read: if resource.contentType == 'image/png';
metadata
Un Map<String, String>
que contiene campos de metadatos adicionales proporcionados por el desarrollador.
// Allow reads if a certain metadata field matches a desired value allow read: if resource.metadata.customProperty == 'customValue';
firestore.get y firestore.exists
Las funciones firestore.get()
y firestore.exists()
le permiten acceder a documentos en Cloud Firestore para evaluar criterios de autorización complejos.
Las funciones firestore.get()
y firestore.exists()
esperan rutas de documentos completamente especificadas. Cuando usa variables para construir rutas para firestore.get()
y firestore.exists()
, necesita escapar explícitamente de las variables usando la sintaxis $(variable)
.
firestore.obtener
Obtenga el contenido de un documento de 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.existe
Compruebe si existe un documento de 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)) } } }
Servicio
El service
es la primera declaración en un archivo de reglas de seguridad de almacenamiento en la nube y especifica a qué servicio se aplicarán estas reglas.
Nombre
name
Se aplicarán las reglas del nombre del servicio. El único valor actual es firebase.storage
.
// Specify the service name service firebase.storage { match /b/{bucket}/o { ... } }
Tipos de datos
El lenguaje de reglas le permite verificar el tipo usando el operador is
.
// For example
a is null
a is string
null
El tipo de datos null
representa un valor que no existe.
allow read: if request.auth != null;
bool
El tipo bool
representa un valor booleano true
o false
.
allow read: if true; // always succeeds allow write: if false; // always fails
Comparación
Los valores booleanos se pueden comparar usando los operadores ==
!=
.
Operaciones booleanas
Operación | Expresión |
---|---|
AND | x && y |
OR | x || y |
NOT | !x |
Las operaciones se cortocircuitan y pueden devolver true
, false
o Error .
allow read: if true || false; // always succeeds, short circuits at true allow write: if false && true; // always fails, short circuits at false
int
y float
Los tipos int
y float
representan números. Los enteros son: 0
, 1
, -2
, etc. , mientras que los flotantes son: 1.0
, -2.0
, 3.33
, etc.
Los enteros son valores de 64 bits con signo y los flotantes son valores compatibles con IEEE 754 de 64 bits. Los valores de tipo int
se obligarán a float
cuando se utilicen en comparaciones y operaciones aritméticas con un valor float
.
Comparación
Los números enteros y flotantes se pueden comparar y ordenar mediante los operadores ==
, !=
, >
, <
, >=
y <=
.
Aritmética
Los números enteros y flotantes se pueden sumar, restar, multiplicar, dividir, modular y negar:
Operación | Expresión |
---|---|
Suma | x + y |
Sustracción | x - y |
Multiplicación | x * y |
División | x / y |
Módulo | x % y |
Negación | -x |
Funciones matematicas
Firebase Security Rules for Cloud Storage también proporciona una serie de funciones de ayuda matemática para simplificar las expresiones:
Función | Descripción |
---|---|
math.ceil(x) | Techo del valor numérico |
math.floor(x) | Piso del valor numérico |
math.round(x) | Redondea el valor de entrada al int más cercano |
math.abs(x) | Valor absoluto de la entrada |
math.isInfinite(x) | Prueba si el valor es ±∞ , devuelve un bool |
math.isNaN(x) | Prueba si el valor no es un número NaN , devuelve un bool |
string
Comparación
Las cadenas se pueden comparar y ordenar lexográficamente usando los operadores ==
, !=
, >
, <
, >=
y <=
.
Concatenación
Las cadenas se pueden concatenar usando el operador +
.
// Concatenate a file name and extension 'file' + '.txt'
Índice y rango
El operador index
, string[]
, devuelve una cadena que contiene el carácter en el índice proporcionado en la cadena.
// Allow reads of files that begin with 'a' match /{fileName} { allow read: if fileName[0] == 'a'; }
El operador de range
, string[i:j]
, devuelve una cadena que contiene los caracteres entre los índices especificados, desde i
(incluido) hasta j
(exclusivo). Si no se especifican i
o j
, por defecto son 0 y el tamaño de la cadena, respectivamente, pero se debe especificar al menos i
o j
para que el rango sea válido.
// Allow reads of files that begin with 'abcdef' match /{fileName} { allow read: if fileName[0:6] == 'abcdef'; }
Los operadores index
y range
generarán un error si los índices proporcionados exceden los límites de la cadena.
size
Devuelve el número de caracteres de la cadena.
// Allow files with names less than 10 characters match /{fileName} { allow write: if fileName.size() < 10; }
matches
Realiza una coincidencia de expresión regular, devuelve true
si la cadena coincide con la expresión regular dada. Utiliza la sintaxis de Google RE2 .
// Allow writes to files which end in ".txt" match /{fileName} { allow write: if fileName.matches('.*\\.txt') }
split
Divide una cadena de acuerdo con una expresión regular proporcionada y devuelve una list
de cadenas. Utiliza la sintaxis de Google RE2 .
// Allow files named "file.*" to be uploaded match /{fileName} { allow write: if fileName.split('.*\\..*')[0] == 'file' }
path
Las rutas son nombres similares a directorios con coincidencia de patrones opcional. La presencia de una barra inclinada /
denota el inicio de un segmento de ruta.
path
Convierte un argumento de string
en una path
.
// Allow reads on a specific file path match /{allFiles=**} { allow read: if allFiles == path('/path/to/file'); }
timestamp
Las marcas de tiempo están en UTC, con valores posibles que comienzan en 0001-01-01T00.00.00Z y terminan en 9999-12-31T23.59.59Z.
Comparación
Las marcas de tiempo se pueden comparar y ordenar mediante los operadores ==
, !=
, >
, <
, >=
y <=
.
Aritmética
Las marcas de tiempo admiten sumas y restas entre marcas de tiempo y duraciones de la siguiente manera:
Expresión | Resultado |
---|---|
timestamp + duration | timestamp |
duration + timestamp | timestamp |
timestamp - duration | timestamp |
timestamp - timestamp | duration |
duration + duration | duration |
duration - duration | duration |
date
Un valor de timestamp
de tiempo que contiene solo el year
, el month
y day
.
// Allow reads on the same day that the resource was created. allow read: if request.time.date() == resource.timeCreated.date()
year
El valor del año como un entero, de 1 a 9999.
// Allow reads on all requests made before 2017 allow read: if request.time.year() < 2017
month
El valor del mes como un entero, de 1 a 12.
// Allow reads on all requests made during the month of January allow read: if request.time.month() == 1;
day
El día actual del mes como un int, del 1 al 31.
// Allow reads on all requests made during the first day of each month allow read: if request.time.day() == 1;
time
Un valor de duration
que contiene la hora actual.
// Allow reads on all requests made before 12PM allow read: if request.time.time() < duration.time(12, 0, 0, 0);
hours
El valor de las horas como un entero, de 0 a 23.
// Allow reads on all requests made before 12PM allow read: if request.time.hours() < 12;
minutes
El valor de los minutos como un int, de 0 a 59.
// Allow reads during even minutes of every hour allow read: if request.time.minutes() % 2 == 0;
seconds
El valor de los segundos como un entero, de 0 a 59.
// Allow reads during the second half of each minute allow read: if request.time.seconds() > 29;
nanos
Los segundos fraccionarios en nanos como un int.
// Allow reads during the first 0.1 seconds of each second allow read: if request.time.nanos() < 100000000;
dayOfWeek
El día de la semana, de 1 (lunes) a 7 (domingo).
// Allow reads on weekdays (Monday to Friday) allow read: if request.time.dayOfWeek() < 6;
dayOfYear
El día del año en curso, del 1 al 366.
// Allow reads every fourth day allow read: if request.time.dayOfYear() % 4 == 0;
toMillis
Devuelve el número actual de milisegundos desde la época de Unix.
// Allow reads if the request is made before a specified time allow read: if request.time.toMillis() < <milliseconds>;
duration
Los valores de duración se representan como segundos más segundos fraccionarios en nanosegundos.
Comparación
Las duraciones se pueden comparar y ordenar usando los operadores ==
, !=
, >
, <
, >=
y <=
.
Aritmética
Las duraciones admiten sumas y restas entre marcas de tiempo y duraciones de la siguiente manera:
Expresión | Resultado |
---|---|
timestamp + duration | timestamp |
duration + timestamp | timestamp |
timestamp - duration | timestamp |
timestamp - timestamp | duration |
duration + duration | duration |
duration - duration | duration |
seconds
El número de segundos en la duración actual. Debe estar entre -315,576,000,000 y +315,576,000,000 inclusive.
nanos
El número de segundos fraccionarios (en nanosegundos) de la duración actual. Debe estar entre -999,999,999 y +999,999,999 inclusive. Para segundos distintos de cero y nanosegundos distintos de cero, los signos de ambos deben estar de acuerdo.
duration.value
Las duraciones se pueden crear usando la función duration.value(int magnitude, string units)
, que crea una duración de tiempo a partir de la magnitud y la unidad dadas.
// All of these durations represent one hour: duration.value(1, "h") duration.value(60, "m") duration.value(3600, "s")
Las posibles unit
son:
Duración | unit |
---|---|
Semanas | w |
Días | d |
Horas | h |
Minutos | m |
Segundos | s |
milisegundos | ms |
nanosegundos | ns |
duration.time
Las duraciones se pueden crear usando la función duration.time(int hours, int minutes, int seconds, int nanoseconds)
, que crea una duración de horas, minutos, segundos y nanosegundos dados.
// Create a four hour, three minute, two second, one nanosecond duration duration.time(4, 3, 2, 1)
list
Una lista contiene una matriz ordenada de valores, que pueden ser de tipo: null
, bool
, int
, float
, string
, path
, list
, map
, timestamp
o duration
.
Dados x
e y
de tipo list
e i
y j
de tipo int
Creación
Para crear una lista, agregue valores entre paréntesis:
// Create a list of strings ['apples', 'grapes', 'bananas', 'cheese', 'goats']
Comparación
Las listas se pueden comparar usando los operadores ==
!=
. La igualdad de dos listas requiere que todos los valores sean iguales.
Índice y rango
El operador index
, list[]
, devuelve el elemento en el índice proporcionado en la lista.
// Allow reads of all files that begin with 'a' match /{fileName} { allow read: if fileName[0] == 'a'; }
El operador de range
, list[i:j]
, devuelve todos los elementos de una lista entre los índices especificados, desde i
(incluido) hasta j
(exclusivo). Si no se especifican i
o j
, por defecto son 0 y el tamaño de la lista, respectivamente, pero se debe especificar al menos i
o j
para que el rango sea válido.
// Allow reads of all files that begin with 'abcdef' match /{fileName} { allow read: if fileName[0:6] == 'abcdef'; }
in
Devuelve true
si el valor deseado está presente en la lista o false
si no está presente.
// Allow read if a filename has the string 'txt' in it match /{fileName} { allow read: if 'txt' in fileName.split('\\.'); }
join
Combina una lista de cadenas en una sola cadena, separadas por la cadena dada.
// Allow reads if the joined array is 'file.txt' allow read: if ['file', 'txt'].join('.') == 'file.txt';
size
El número de elementos en la lista.
// Allow read if there are three items in our list allow read: if ['foo', 'bar', 'baz'].size() == 3;
hasAll
Devuelve true
si todos los valores están presentes en la lista.
// Allow read if one list has all items in the other list allow read: if ['file', 'txt'].hasAll(['file', 'txt']);
map
Un mapa contiene pares clave/valor, donde las claves son cadenas y los valores pueden ser cualquiera de: null
, bool
, int
, float
, string
, path
, list
, map
, timestamp
o duration
.
Creación
Para crear un mapa, agregue pares clave/valor entre llaves:
// Create a map of strings to strings { 'mercury': 'mars', 'rain': 'cloud', 'cats': 'dogs', }
Comparación
Los mapas se pueden comparar usando los operadores ==
!=
. La igualdad de dos mapas requiere que todas las claves estén presentes en ambos mapas y que todos los valores sean iguales.
Índice
Se accede a los valores en un mapa usando la notación de paréntesis o de puntos:
// Access custom metadata properties allow read: if resource.metadata.property == 'property' allow write: if resource.metadata['otherProperty'] == 'otherProperty'
Si una clave no está presente, se devolverá un error
.
in
Devuelve true
si la clave deseada está presente en el mapa o false
si no está presente.
// Allow reads if a property is present in the custom metadata allow read: if property in resource.metadata;
size
El número de claves en el mapa.
// Allow reads if there's exactly one custom metadata key allow read: if resource.metadata.size() == 1;
keys
Una lista de todas las claves en el mapa.
// Allow reads if the first metadata key is 'myKey' allow read: if resource.metadata.keys()[0] == 'myKey';
values
Una lista de todos los valores en el mapa, en orden clave.
// Allow reads if the first metadata value is 'myValue' allow read: if resource.metadata.values()[0] == 'myValue';
errores
Evaluación de errores
Las reglas de seguridad de Firebase para Cloud Storage continúan con la evaluación cuando se encuentran errores. Esto es útil porque condicional &&
y ||
las expresiones pueden absorber un error si el condicional se cortocircuitaría a false
o true
respectivamente. Por ejemplo:
Expresión | Resultado |
---|---|
error && true | error |
error && false | false |
error || true | true |
error || false | error |
Los lugares comunes donde se generan errores son: división por cero, acceder a valores en una lista o mapa que no existe y pasar valores del tipo incorrecto a una función.
// 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');