Las reglas de seguridad de Firebase aprovechan los lenguajes flexibles, poderosos y personalizados que admiten un rango amplio de complejidad y nivel de detalle. Puedes hacer que las reglas para tu app sean tan específicas o generales como necesites. Las reglas de Realtime Database usan una sintaxis similar a la de JavaScript en una estructura JSON.
Las reglas de Cloud Firestore y Cloud Storage usan un lenguaje basado en el Common Expression Language (CEL), que se basa en CEL con declaraciones match
y allow
que admiten el acceso condicional.
Sin embargo, hay una curva de aprendizaje debido a que estos son lenguajes personalizados. Usa esta guía para comprender mejor el lenguaje de las reglas a medida que profundizas en reglas más complejas.
Selecciona un producto para obtener más información sobre sus reglas.
Estructura básica
Cloud Firestore
Las reglas de seguridad de Firebase en Cloud Firestore y Cloud Storage utilizan la siguiente estructura y sintaxis:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
Es importante comprender los siguientes conceptos clave cuando compiles las reglas:
- Solicitud: El método o los métodos invocados en la declaración
allow
que permites que se ejecuten. Los métodos estándar songet
,list
,create
,update
ydelete
. Los métodos de convenienciaread
ywrite
permiten un amplio acceso de lectura y escritura en la base de datos o ruta de almacenamiento especificada. - Ruta de acceso: La ubicación de la base de datos o del almacenamiento, representada como una ruta URI.
- Regla: La declaración
allow
, que incluye una condición que permite una solicitud si se evalúa como verdadera.
Cada uno de estos conceptos se describe con más detalle a continuación.
Cloud Storage
Las reglas de seguridad de Firebase en Cloud Firestore y Cloud Storage utilizan la siguiente estructura y sintaxis:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
Es importante comprender los siguientes conceptos clave cuando compiles las reglas:
- Solicitud: El método o los métodos invocados en la declaración
allow
que permites que se ejecuten. Los métodos estándar songet
,list
,create
,update
ydelete
. Los métodos de convenienciaread
ywrite
permiten un amplio acceso de lectura y escritura en la base de datos o ruta de almacenamiento especificada. - Ruta de acceso: La ubicación de la base de datos o del almacenamiento, representada como una ruta URI.
- Regla: La declaración
allow
, que incluye una condición que permite una solicitud si se evalúa como verdadera.
Cada uno de estos conceptos se describe con más detalle a continuación.
Realtime Database
En Realtime Database, las reglas de seguridad de Firebase son expresiones similares a las de JavaScript, contenidas en un documento JSON.
Usan la siguiente sintaxis:
{
"rules": {
"<<path>>": {
// Allow the request if the condition for each method is true.
".read": <<condition>>,
".write": <<condition>>,
".validate": <<condition>>
}
}
}
Hay tres elementos básicos en la regla:
- Ruta: La ubicación de la base de datos. Esto duplica la estructura JSON de tu base de datos.
- Solicitud: Estos son los métodos que usa la regla para otorgar acceso. Las reglas
read
ywrite
otorgan acceso amplio de lectura y escritura, mientras que las reglasvalidate
actúan como verificación secundaria para otorgar acceso según los datos entrantes o existentes. - Condición: La condición que permite una solicitud si se evalúa como verdadera.
Construcciones de las reglas
Cloud Firestore
Los elementos básicos de una regla en Cloud Firestore y Cloud Storage son los siguientes:
- La declaración
service
declara el producto de Firebase al que se aplican las reglas. - El bloque
match
define una ruta en la base de datos o en el depósito de almacenamiento al que se aplican las reglas. - La declaración
allow
proporciona condiciones para otorgar acceso, diferenciadas por métodos. Los métodos compatibles songet
,list
,create
,update
ydelete
, y los métodos de conveniencia sonread
ywrite
. - Las declaraciones
function
opcionales proporcionan la capacidad de combinar y unir condiciones para su uso en varias reglas.
El service
contiene uno o más bloques match
con declaraciones allow
que proporcionan condiciones que otorgan acceso a las solicitudes. Las variables request
y resource
están disponibles para su uso en condiciones de reglas.
El lenguaje de las reglas de seguridad de Firebase también admite declaraciones function
.
Versión de sintaxis
La declaración syntax
indica la versión del lenguaje de reglas de Firebase que se usa para escribir el origen. La última versión del lenguaje es v2
.
rules_version = '2';
service cloud.firestore {
...
}
Si no se proporciona una declaración rules_version
, las reglas se evaluarán con el motor v1
.
Servicio
La declaración service
define a qué producto o servicio de Firebase se aplican tus reglas. Solo puedes incluir una declaración service
por archivo de origen.
Cloud Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Cloud Storage
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Si defines reglas para Cloud Firestore y Cloud Storage mediante Firebase CLI, deberás mantenerlas en archivos independientes.
Match
Un bloque match
declara un patrón path
que se compara con la
ruta para la operación solicitada (la request.path
entrante). El cuerpo
de match
debe tener uno o más bloques match
anidados, declaraciones allow
o declaraciones function
. La ruta en los bloques match
anidados es relativa a la ruta en el bloque match
superior.
El patrón path
es un nombre similar a un directorio que puede incluir variables o comodines. El patrón path
permite coincidencias de segmento de ruta única y de varias rutas. Cualquier variable vinculada en un path
es visible dentro del alcance de match
o de cualquier alcance anidado en el que se declare path
.
Las coincidencias con un patrón path
pueden ser parciales o completas:
- Coincidencias parciales: El patrón
path
es una coincidencia de prefijo derequest.path
. - Coincidencias completas: El patrón
path
coincide con toda larequest.path
.
Cuando se realiza una coincidencia completa, se evalúan las reglas dentro del bloque. Cuando se obtiene una coincidencia parcial, se evalúan las reglas match
anidadas para ver si alguna path
anidada completará la coincidencia.
Las reglas en cada match
completa se evalúan para permitir o no la solicitud. Si alguna regla coincidente otorga acceso, se permite la solicitud. Si ninguna regla coincidente otorga acceso, se deniega la solicitud.
// 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.
}
}
Como se muestra en el ejemplo anterior, las declaraciones path
admiten las siguientes variables:
- Comodín en segmento único: una variable de comodín se declara en una ruta mediante la unión de una variable entre llaves:
{variable}
. Esta variable es accesible dentro de la declaraciónmatch
como unastring
. - Comodín recurrente: el comodín recurrente, o de varios segmentos, coincide con varios segmentos de la ruta de acceso en una ruta o debajo de ella. Este comodín coincide con todas las rutas debajo de la ubicación donde lo configuraste. Para declararlo, agrega la string
=**
al final de tu variable de segmento:{variable=**}
. Esta variable es accesible en la declaraciónmatch
como un objetopath
.
Allow
El bloque match
contiene una o más declaraciones allow
. Estas son tus reglas reales. Puedes aplicar reglas allow
a uno o más métodos. Las condiciones de una declaración allow
deben evaluarse como verdaderas para que Cloud Firestore o Cloud Storage otorguen acceso a cualquier solicitud entrante. También puedes escribir declaraciones allow
sin condiciones; por ejemplo, allow read
. Sin embargo, si la declaración allow
no incluye una condición, siempre permitirá la solicitud para ese método.
Si se cumple alguna de las reglas allow
para el método, se permite la solicitud. Además, si una regla más amplia otorga acceso, las reglas lo otorgan y, además, ignoran cualquier otra regla detallada que pueda limitar el acceso.
Considera el siguiente ejemplo, en el que cualquier usuario puede leer o borrar cualquiera de sus propios archivos. Una regla más detallada solo permite escrituras si el usuario que solicita la escritura es el propietario del archivo y es un archivo PNG. Un usuario puede borrar cualquier archivo en la ruta secundaria, incluso si no es PNG, ya que la regla anterior lo permite.
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 != null && 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 != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
Método
Cada declaración allow
incluye un método que otorga acceso a las solicitudes entrantes del mismo método.
Método | Tipo de solicitud |
---|---|
Métodos de conveniencia | |
read |
Cualquier tipo de solicitud de lectura |
write |
Cualquier tipo de solicitud de escritura |
Métodos estándar | |
get |
Solicitudes de lectura de documentos o archivos individuales |
list |
Solicitudes de lectura para búsquedas y colecciones |
create |
Escribir documentos o archivos nuevos |
update |
Escribir en documentos de bases de datos existentes o actualizar metadatos de archivos |
delete |
Borra datos |
No puedes superponer métodos de lectura en el mismo bloque match
o métodos de escritura en conflicto en la misma declaración path
.
Por ejemplo, las siguientes reglas fallarían:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && 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 != null && request.auth.uid == "me";
}
}
}
Función
A medida que tus reglas de seguridad se vuelvan más complejas, te recomendamos agrupar conjuntos de condiciones en funciones que puedas volver a usar en tu conjunto de reglas. Las reglas de seguridad admiten funciones personalizadas. La sintaxis de las funciones personalizadas es similar a la de JavaScript, pero las funciones de reglas de seguridad se escriben en un lenguaje específico del dominio y tiene algunas limitaciones importantes:
- Las funciones solo pueden incluir una sola declaración
return
. No pueden contener lógica adicional. Por ejemplo, no pueden ejecutar bucles ni llamar a servicios externos. - Las funciones pueden acceder automáticamente a funciones y variables desde el permiso en el que se definen. Por ejemplo, una función definida en el alcance
service cloud.firestore
tiene acceso a la variableresource
y a las funciones integradas, comoget()
yexists()
. - Las funciones pueden llamar a otras funciones, pero no hacer referencia a sí mismas. La profundidad total de la pila de llamadas se limita a 20.
- En la versión de reglas
v2
, las funciones pueden definir variables con la palabra clavelet
. Las funciones pueden tener hasta 10 vinculaciones let, pero deben terminar con una sentencia return.
Una función se define con la palabra clave function
y usa cero o más argumentos. Por ejemplo, puedes combinar los dos tipos de condiciones usados en los ejemplos anteriores en una única función:
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();
}
}
}
A continuación, se muestra un ejemplo que incluye argumentos de funciones y asignaciones let. Las declaraciones de asignaciones let se deben separar con punto y coma.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Observa cómo la asignación isAdmin
aplica una búsqueda de la colección de administradores. Para
una evaluación diferida que no requiere búsquedas innecesarias, aprovecha la
naturaleza de cortocircuito de las comparaciones &&
(AND) y ||
(OR) para llamar a una segunda
función solo si isAuthor
se muestra como verdadero (para comparaciones &&
) o falso
(para comparaciones ||
).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
Usar funciones en las reglas de seguridad facilita su mantenimiento a medida que aumenta su complejidad.
Cloud Storage
Los elementos básicos de una regla en Cloud Firestore y Cloud Storage son los siguientes:
- La declaración
service
declara el producto de Firebase al que se aplican las reglas. - El bloque
match
define una ruta en la base de datos o en el depósito de almacenamiento al que se aplican las reglas. - La declaración
allow
proporciona condiciones para otorgar acceso, diferenciadas por métodos. Los métodos compatibles songet
,list
,create
,update
ydelete
, y los métodos de conveniencia sonread
ywrite
. - Las declaraciones
function
opcionales proporcionan la capacidad de combinar y unir condiciones para su uso en varias reglas.
El service
contiene uno o más bloques match
con declaraciones allow
que proporcionan condiciones que otorgan acceso a las solicitudes. Las variables request
y resource
están disponibles para su uso en condiciones de reglas.
El lenguaje de las reglas de seguridad de Firebase también admite declaraciones function
.
Versión de sintaxis
La declaración syntax
indica la versión del lenguaje de reglas de Firebase que se usa para escribir el origen. La última versión del lenguaje es v2
.
rules_version = '2';
service cloud.firestore {
...
}
Si no se proporciona una declaración rules_version
, las reglas se evaluarán con el motor v1
.
Servicio
La declaración service
define a qué producto o servicio de Firebase se aplican tus reglas. Solo puedes incluir una declaración service
por archivo de origen.
Cloud Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Cloud Storage
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Si defines reglas para Cloud Firestore y Cloud Storage mediante Firebase CLI, deberás mantenerlas en archivos independientes.
Match
Un bloque match
declara un patrón path
que se compara con la
ruta para la operación solicitada (la request.path
entrante). El cuerpo
de match
debe tener uno o más bloques match
anidados, declaraciones allow
o declaraciones function
. La ruta en los bloques match
anidados es relativa a la ruta en el bloque match
superior.
El patrón path
es un nombre similar a un directorio que puede incluir variables o comodines. El patrón path
permite coincidencias de segmento de ruta única y de varias rutas. Cualquier variable vinculada en un path
es visible dentro del alcance de match
o de cualquier alcance anidado en el que se declare path
.
Las coincidencias con un patrón path
pueden ser parciales o completas:
- Coincidencias parciales: El patrón
path
es una coincidencia de prefijo derequest.path
. - Coincidencias completas: El patrón
path
coincide con toda larequest.path
.
Cuando se realiza una coincidencia completa, se evalúan las reglas dentro del bloque. Cuando se obtiene una coincidencia parcial, se evalúan las reglas match
anidadas para ver si alguna path
anidada completará la coincidencia.
Las reglas en cada match
completa se evalúan para permitir o no la solicitud. Si alguna regla coincidente otorga acceso, se permite la solicitud. Si ninguna regla coincidente otorga acceso, se deniega la solicitud.
// 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.
}
}
Como se muestra en el ejemplo anterior, las declaraciones path
admiten las siguientes variables:
- Comodín en segmento único: una variable de comodín se declara en una ruta mediante la unión de una variable entre llaves:
{variable}
. Esta variable es accesible dentro de la declaraciónmatch
como unastring
. - Comodín recurrente: el comodín recurrente, o de varios segmentos, coincide con varios segmentos de la ruta de acceso en una ruta o debajo de ella. Este comodín coincide con todas las rutas debajo de la ubicación donde lo configuraste. Para declararlo, agrega la string
=**
al final de tu variable de segmento:{variable=**}
. Esta variable es accesible en la declaraciónmatch
como un objetopath
.
Allow
El bloque match
contiene una o más declaraciones allow
. Estas son tus reglas reales. Puedes aplicar reglas allow
a uno o más métodos. Las condiciones de una declaración allow
deben evaluarse como verdaderas para que Cloud Firestore o Cloud Storage otorguen acceso a cualquier solicitud entrante. También puedes escribir declaraciones allow
sin condiciones; por ejemplo, allow read
. Sin embargo, si la declaración allow
no incluye una condición, siempre permitirá la solicitud para ese método.
Si se cumple alguna de las reglas allow
para el método, se permite la solicitud. Además, si una regla más amplia otorga acceso, las reglas lo otorgan y, además, ignoran cualquier otra regla detallada que pueda limitar el acceso.
Considera el siguiente ejemplo, en el que cualquier usuario puede leer o borrar cualquiera de sus propios archivos. Una regla más detallada solo permite escrituras si el usuario que solicita la escritura es el propietario del archivo y es un archivo PNG. Un usuario puede borrar cualquier archivo en la ruta secundaria, incluso si no es PNG, ya que la regla anterior lo permite.
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 != null && 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 != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
Método
Cada declaración allow
incluye un método que otorga acceso a las solicitudes entrantes del mismo método.
Método | Tipo de solicitud |
---|---|
Métodos de conveniencia | |
read |
Cualquier tipo de solicitud de lectura |
write |
Cualquier tipo de solicitud de escritura |
Métodos estándar | |
get |
Solicitudes de lectura de documentos o archivos individuales |
list |
Solicitudes de lectura para búsquedas y colecciones |
create |
Escribir documentos o archivos nuevos |
update |
Escribir en documentos de bases de datos existentes o actualizar metadatos de archivos |
delete |
Borra datos |
No puedes superponer métodos de lectura en el mismo bloque match
o métodos de escritura en conflicto en la misma declaración path
.
Por ejemplo, las siguientes reglas fallarían:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && 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 != null && request.auth.uid == "me";
}
}
}
Función
A medida que tus reglas de seguridad se vuelvan más complejas, te recomendamos agrupar conjuntos de condiciones en funciones que puedas volver a usar en tu conjunto de reglas. Las reglas de seguridad admiten funciones personalizadas. La sintaxis de las funciones personalizadas es similar a la de JavaScript, pero las funciones de reglas de seguridad se escriben en un lenguaje específico del dominio y tiene algunas limitaciones importantes:
- Las funciones solo pueden incluir una sola declaración
return
. No pueden contener lógica adicional. Por ejemplo, no pueden ejecutar bucles ni llamar a servicios externos. - Las funciones pueden acceder automáticamente a funciones y variables desde el permiso en el que se definen. Por ejemplo, una función definida en el alcance
service cloud.firestore
tiene acceso a la variableresource
y a las funciones integradas, comoget()
yexists()
. - Las funciones pueden llamar a otras funciones, pero no hacer referencia a sí mismas. La profundidad total de la pila de llamadas se limita a 20.
- En la versión de reglas
v2
, las funciones pueden definir variables con la palabra clavelet
. Las funciones pueden tener hasta 10 vinculaciones let, pero deben terminar con una sentencia return.
Una función se define con la palabra clave function
y usa cero o más argumentos. Por ejemplo, puedes combinar los dos tipos de condiciones usados en los ejemplos anteriores en una única función:
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();
}
}
}
A continuación, se muestra un ejemplo que incluye argumentos de funciones y asignaciones let. Las declaraciones de asignaciones let se deben separar con punto y coma.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Observa cómo la asignación isAdmin
aplica una búsqueda de la colección de administradores. Para
una evaluación diferida que no requiere búsquedas innecesarias, aprovecha la
naturaleza de cortocircuito de las comparaciones &&
(AND) y ||
(OR) para llamar a una segunda
función solo si isAuthor
se muestra como verdadero (para comparaciones &&
) o falso
(para comparaciones ||
).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
Usar funciones en las reglas de seguridad facilita su mantenimiento a medida que aumenta su complejidad.
Realtime Database
Como se describió anteriormente, las reglas de Realtime Database incluyen tres elementos básicos: la ubicación de la base de datos como una duplicación de la estructura JSON de la base de datos, el tipo de solicitud y la condición que otorga el acceso.
Ubicación de la base de datos
La estructura de tus reglas debe seguir la de los datos que almacenaste en tu base de datos. Por ejemplo, en una app de chat con una lista de mensajes, es posible que tengas datos que se parezcan a los siguientes:
{
"messages": {
"message0": {
"content": "Hello",
"timestamp": 1405704370369
},
"message1": {
"content": "Goodbye",
"timestamp": 1405704395231
},
...
}
}
Tus reglas deben duplicar esa estructura. Por ejemplo:
{
"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()"
}
}
}
}
Como se muestra en el ejemplo anterior, las reglas de Realtime Database admiten una variable $location
que coincida con segmentos de la ruta de acceso. Usa el prefijo $
delante del segmento de la ruta de acceso para hacer coincidir tu regla con los nodos secundarios en la ruta.
{
"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')"
}
}
}
}
}
También puedes usar $variable
en paralelo con nombres de ruta de acceso 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
En Realtime Database, hay tres tipos de reglas. Dos de estos tipos de reglas (read
y write
) se aplican al método de una solicitud entrante. El tipo de regla validate
aplica estructuras de datos y valida el formato y el contenido de los datos.
Las reglas ejecutan reglas .validate
después de verificar que una regla .write
otorga acceso.
Tipos de reglas | |
---|---|
.read | Describe si los usuarios pueden leer los datos y cuándo pueden hacerlo. |
.write | Indica si se permite la escritura de datos y en qué momento. |
.validate | Define el aspecto de un valor con formato correcto, si este tiene atributos secundarios y el tipo de datos. |
De acuerdo con la configuración predeterminada, si no hay una regla que lo permita, se rechaza el acceso a la ruta de acceso.
Cómo compilar condiciones
Cloud Firestore
Una condición es una expresión booleana que determina si se debe permitir o rechazar una operación en particular. Las variables request
y resource
proporcionan contexto para esas condiciones.
La variable request
La variable request
incluye los siguientes campos y la información correspondiente:
request.auth
Un token web JSON (JWT) que contiene credenciales de autenticación de Firebase Authentication. El token auth
contiene un conjunto de reclamaciones estándar y cualquier reclamación personalizada que crees a través de Firebase Authentication. Obtén más información sobre las reglas de seguridad y Firebase Authentication.
request.method
request.method
puede ser cualquiera de los métodos estándar o uno personalizado. Los métodos de conveniencia read
y write
también existen para simplificar las reglas de escritura que se aplican a todos los métodos estándar de solo lectura o solo escritura, respectivamente.
request.params
request.params
incluye cualquier dato no relacionado específicamente con el request.resource
que podría ser útil para la evaluación. En la práctica, este mapa debe estar vacío para todos los métodos estándar y debe contener datos que no sean de recursos de métodos personalizados. En los servicios se debe tener cuidado de no cambiar el nombre ni modificar el tipo de cualquiera de las claves y los valores presentados como parámetros.
request.path
request.path
es la ruta para el resource
de destino. Esta ruta es relativa al servicio. Los segmentos de ruta que contienen caracteres seguros que no son URL, como /
, están codificados en URL.
La variable resource
resource
es el valor actual en el servicio representado como un mapa de pares clave-valor. Hacer referencia a resource
en una condición generará, como máximo, una lectura del valor del servicio. Esta búsqueda se contará en cualquier cuota del recurso relacionada con el servicio. Para las solicitudes get
, resource
solo se considerará en la cuota si se deniega.
Operadores y prioridad de operadores
Usa la tabla que está a continuación como referencia para los operadores y su prioridad correspondiente en las reglas de Cloud Firestore y Cloud Storage.
Dadas las expresiones arbitrarias a
y b
, un campo f
y un índice i
.
Operador | Descripción | Asociatividad |
---|---|---|
a[i] a() a.f |
Acceso a índice, llamada o campo | de izquierda a derecha |
!a -a |
Negación unaria | De derecha a izquierda |
a/b a%b a*b |
Operadores multiplicativos | de izquierda a derecha |
a+b a-b |
Operadores aditivos | de izquierda a derecha |
a>b a>=b a<=b |
Operadores relacionales | de izquierda a derecha |
a in b |
Existencia en lista o mapa | de izquierda a derecha |
a is type |
Comparación de tipos, en la que type puede ser bool, int, float,
number, string, list, map, timestamp, duration, path o latlng |
de izquierda a derecha |
a==b a!=b |
Operadores de comparación | de izquierda a derecha |
a && b |
Condicional AND | de izquierda a derecha |
a || b |
Condicional OR | de izquierda a derecha |
a ? true_value : false_value |
Expresión ternaria | de izquierda a derecha |
Cloud Storage
Una condición es una expresión booleana que determina si se debe permitir o rechazar una operación en particular. Las variables request
y resource
proporcionan contexto para esas condiciones.
La variable request
La variable request
incluye los siguientes campos y la información correspondiente:
request.auth
Un token web JSON (JWT) que contiene credenciales de autenticación de Firebase Authentication. El token auth
contiene un conjunto de reclamaciones estándar y cualquier reclamación personalizada que crees a través de Firebase Authentication. Obtén más información sobre las reglas de seguridad y Firebase Authentication.
request.method
request.method
puede ser cualquiera de los métodos estándar o uno personalizado. Los métodos de conveniencia read
y write
también existen para simplificar las reglas de escritura que se aplican a todos los métodos estándar de solo lectura o solo escritura, respectivamente.
request.params
request.params
incluye cualquier dato no relacionado específicamente con el request.resource
que podría ser útil para la evaluación. En la práctica, este mapa debe estar vacío para todos los métodos estándar y debe contener datos que no sean de recursos de métodos personalizados. En los servicios se debe tener cuidado de no cambiar el nombre ni modificar el tipo de cualquiera de las claves y los valores presentados como parámetros.
request.path
request.path
es la ruta para el resource
de destino. Esta ruta es relativa al servicio. Los segmentos de ruta que contienen caracteres seguros que no son URL, como /
, están codificados en URL.
La variable resource
resource
es el valor actual en el servicio representado como un mapa de pares clave-valor. Hacer referencia a resource
en una condición generará, como máximo, una lectura del valor del servicio. Esta búsqueda se contará en cualquier cuota del recurso relacionada con el servicio. Para las solicitudes get
, resource
solo se considerará en la cuota si se deniega.
Operadores y prioridad de operadores
Usa la tabla que está a continuación como referencia para los operadores y su prioridad correspondiente en las reglas de Cloud Firestore y Cloud Storage.
Dadas las expresiones arbitrarias a
y b
, un campo f
y un índice i
.
Operador | Descripción | Asociatividad |
---|---|---|
a[i] a() a.f |
Acceso a índice, llamada o campo | de izquierda a derecha |
!a -a |
Negación unaria | De derecha a izquierda |
a/b a%b a*b |
Operadores multiplicativos | de izquierda a derecha |
a+b a-b |
Operadores aditivos | de izquierda a derecha |
a>b a>=b a<=b |
Operadores relacionales | de izquierda a derecha |
a in b |
Existencia en lista o mapa | de izquierda a derecha |
a is type |
Comparación de tipos, en la que type puede ser bool, int, float,
number, string, list, map, timestamp, duration, path o latlng |
de izquierda a derecha |
a==b a!=b |
Operadores de comparación | de izquierda a derecha |
a && b |
Condicional AND | de izquierda a derecha |
a || b |
Condicional OR | de izquierda a derecha |
a ? true_value : false_value |
Expresión ternaria | de izquierda a derecha |
Realtime Database
Una condición es una expresión booleana que determina si se debe permitir o rechazar una operación en particular. Puedes definir esas condiciones en las reglas de Realtime Database de las siguientes maneras.
Variables predefinidas
Hay una serie de variables predefinidas útiles a las que se puede acceder dentro de una definición de reglas. A continuación, se incluye un breve resumen de cada una:
Variables predefinidas | |
---|---|
now | La hora actual en milisegundos desde la época Linux. Esto funciona particularmente bien para validar las marcas de tiempo creadas con firebase.database.ServerValue.TIMESTAMP del SDK. |
root | Una RuleDataSnapshot que representa la ruta de acceso de raíz en la base de datos de Firebase, tal como existe antes de la operación que se intenta ejecutar. |
newData | Una RuleDataSnapshot que representa los datos como existirían después de la operación que se intenta ejecutar. Incluye los datos nuevos que se escriben y los datos existentes. |
data | Una RuleDataSnapshot que representa los datos como existían antes de la operación que se intenta ejecutar. |
Variables $ | Ruta de acceso de comodín que se usa para representar los ID y las claves secundarias dinámicas. |
auth | Representa la carga útil del token de un usuario autenticado. |
Estas variables pueden usarse en cualquier sección de tus reglas. Por ejemplo, las siguientes reglas de seguridad garantizan que los datos escritos en el nodo /foo/
deben ser una string de 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" } } }
Reglas basadas en datos
Cualquier dato en tu base de datos se puede usar en tus reglas. Con las variables predefinidas root
, data
y newData
, puedes acceder a cualquier ruta como existiría antes o después de un evento de escritura.
Considera este ejemplo, que permite operaciones de escritura siempre que el valor del nodo /allow_writes/
sea true
, el nodo principal no tenga una marca readOnly
y haya un elemento secundario llamado foo
en los datos recién escritos:
".write": "root.child('allow_writes').val() === true && !data.parent().child('readOnly').exists() && newData.child('foo').exists()"
Reglas basadas en búsquedas
Si bien no puedes usar reglas como filtros, puedes limitar el acceso a subconjuntos de datos mediante el uso de parámetros de consulta en tus reglas. Usa expresiones query.
en tus reglas para otorgar acceso de lectura o escritura en función de los parámetros de consulta.
Por ejemplo, la siguiente regla basada en consultas usa reglas de seguridad basadas en usuarios y en consultas para restringir el acceso a los datos de la colección baskets
solo a los carritos de compra que posee el usuario activo:
"baskets": {
".read": "auth.uid !== null &&
query.orderByChild === 'owner' &&
query.equalTo === auth.uid" // restrict basket access to owner of basket
}
La siguiente consulta, que incluye los parámetros de consulta en la regla, se ejecutaría correctamente:
db.ref("baskets").orderByChild("owner")
.equalTo(auth.currentUser.uid)
.on("value", cb) // Would succeed
Sin embargo, las consultas que no incluyen los parámetros en la regla producirían un error PermissionDenied
:
db.ref("baskets").on("value", cb) // Would fail with PermissionDenied
Además, puedes usar reglas basadas en consultas para limitar la cantidad de datos que un cliente descarga mediante operaciones de lectura.
Por ejemplo, la siguiente regla limita el acceso de lectura a los primeros 1,000 resultados de una consulta únicamente, los cuales se ordenan por prioridad:
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)
Las siguientes expresiones query.
están disponibles en las reglas de seguridad de Realtime Database.
Expresiones de reglas basadas en consultas | ||
---|---|---|
Expresión | Tipo | Descripción |
query.orderByKey query.orderByPriority query.orderByValue |
booleana | Verdadero para consultas ordenadas según la clave, la prioridad o el valor. De lo contrario, el valor es falso. |
query.orderByChild | string nula |
Usa una string para representar la ruta de acceso relativa a un nodo secundario. Por ejemplo, query.orderByChild === "address/zip" . Si la consulta no se ordena según un nodo secundario, este valor es nulo.
|
query.startAt query.endAt query.equalTo |
string número booleana nula |
Recupera los límites de la consulta en ejecución o muestra el valor nulo si no se estableció ningún límite. |
query.limitToFirst query.limitToLast |
número nula |
Recupera el límite de la consulta en ejecución o muestra el valor nulo si no se estableció ningún límite. |
Operadores
Las reglas de Realtime Database admiten una cantidad de operadores que puedes usar para combinar variables en la declaración de condición. Consulta la lista completa de operadores en la documentación de referencia.
Cómo crear condiciones
Tus condiciones reales variarán según el acceso que desees otorgar. Las reglas ofrecen intencionalmente un enorme grado de flexibilidad, por lo que las reglas de tu app pueden ser tan simples o complejas como necesites.
Si deseas obtener información sobre cómo crear reglas simples y listas para la producción, consulta las reglas básicas de seguridad.