Regla: tipos
.leer
Otorga a un cliente acceso de lectura a una ubicación de Firebase Realtime Database.
Una regla .read
es un tipo de regla de seguridad que otorga a un cliente acceso de lectura a una ubicación de Firebase Realtime Database. Por ejemplo:
".read": "auth != null && auth.provider == 'twitter'"
El valor de una regla .read
es una cadena, que se evalúa como un subconjunto de la sintaxis de expresión de JavaScript con algunos cambios de comportamiento para aumentar la claridad y la corrección. Una regla .read
que otorga permiso para leer una ubicación también permitirá la lectura de cualquier descendiente de esa ubicación, incluso si los descendientes tienen sus propias reglas .read
que fallan.
Una regla .read
tiene acceso a todas las variables de regla de Firebase Realtime Database excepto newData
.
.escribir
Otorga a un cliente acceso de escritura a una ubicación de Firebase Realtime Database.
Una regla .write
es un tipo de regla de seguridad que otorga a un cliente acceso de escritura a una ubicación de Firebase Realtime Database. Por ejemplo:
".write": "auth != null && auth.token.isAdmin == true"
El valor de una regla .write
es una cadena, que se evalúa como un subconjunto de la sintaxis de expresión de JavaScript con algunos cambios de comportamiento para aumentar la claridad y la corrección. Una regla .write
que otorga permiso para escribir en una ubicación también permitirá escribir a cualquier descendiente de esa ubicación, incluso si los descendientes tienen sus propias reglas .write
que fallan.
Una regla .write
tiene acceso a todas las variables de reglas de Firebase Realtime Database.
.validar
Se utiliza una vez que una regla .write
ha otorgado acceso, para garantizar que los datos que se escriben se ajusten a un esquema específico.
Una regla .validate
se utiliza una vez que una regla .write
ha otorgado acceso, para garantizar que los datos que se escriben cumplan con un estándar específico. Además de que un .write
otorgue acceso, todas las reglas .validate
relevantes deben tener éxito antes de que se permita una escritura. Por ejemplo:
".validate": "newData.hasChildren(['name', 'age'])"
El valor de una regla .validate
es una cadena, que se evalúa como un subconjunto de la sintaxis de expresión de JavaScript con algunos cambios de comportamiento para aumentar la claridad y la corrección.
Una regla .validate
tiene acceso a todas las variables de reglas de Firebase Realtime Database.
.indexOn
Mejora el rendimiento de las consultas al indicarle a Firebase Realtime Database qué claves desea que se indexen sus datos.
La regla .indexOn
indica a los servidores de Firebase Realtime Database que indexen claves específicas en sus datos para mejorar el rendimiento de sus consultas. Por ejemplo, dada una base de datos con una colección de datos de dinosaurios, podemos decirle a Firebase Realtime Database que optimice las consultas, antes de que sean devueltas desde los servidores, agregando esta regla:
{
"rules": {
"dinosaurs": {
".indexOn": ["height", "length"]
}
}
}
Puede encontrar más información sobre la regla .indexOn
consultando la sección de la guía de seguridad sobre indexación de sus datos .
Regla: variables
autenticación
Una variable que contiene la carga útil del token si un cliente está autenticado, o null
si el cliente no está autenticado.
Firebase Realtime Database le permite autenticarse fácilmente en varios proveedores integrados y generará tokens de autenticación para ellos. Después de que un usuario se autentique con uno de los proveedores integrados, la variable de autenticación contendrá lo siguiente:
Campo | Descripción |
---|---|
provider | El método de autenticación utilizado (por ejemplo, "contraseña", "anónimo", "facebook", "github", "google" o "twitter"). |
uid | Una identificación de usuario única, garantizada para ser única en todos los proveedores. |
token | El contenido del token de ID de autenticación de Firebase. Consulte auth.token . |
Como ejemplo, podríamos tener una regla como la siguiente para permitir a los usuarios crear comentarios siempre que almacenen su ID de usuario con el comentario:
{
"rules": {
".read": true,
"$comment": {
".write": "!data.exists() && newData.child('user_id').val() == auth.uid"
}
}
}
También podríamos establecer una regla como la siguiente para permitir a los usuarios crear comentarios siempre que hayan iniciado sesión con Facebook:
{
"rules": {
".read": true,
"$comment": {
".write": "!data.exists() && auth.provider == 'facebook'"
}
}
}
token de autenticación
Una variable que contiene el contenido del token de ID de autenticación de Firebase.
El 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 email . Algunos proveedores verifican automáticamente las direcciones de correo electrónico de su propiedad. |
phone_number | El número de teléfono asociado con la cuenta, si está presente. |
name | El nombre para mostrar del usuario, si está configurado. |
sub | El UID de Firebase del usuario. Esto es único dentro de un proyecto. |
firebase.identities | Diccionario de todas las identidades que están 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 | El ID de inquilino asociado con la cuenta, si está presente. por ejemplo, tenant2-m6tyz |
Si utiliza autenticación personalizada, auth.token
también contiene cualquier reclamo personalizado especificado por el desarrollador.
Todos estos valores se pueden utilizar dentro de las reglas. Por ejemplo, para restringir el acceso a cuentas de Google asociadas a una dirección de gmail.com, podríamos agregar la regla:
{
"rules": {
".read": "auth != null",
"gmailUsers": {
"$uid": {
".write": "auth.token.email_verified == true && auth.token.email.matches(/.*@gmail.com$/)"
}
}
}
}
Para completar, también se incluyen los siguientes campos en auth.token
, pero es poco probable que sean útiles para las reglas.
Campo | Descripción |
---|---|
iss | El emisor del token. |
aud | La audiencia del token. |
auth_time | La última vez que el usuario se autenticó con una credencial utilizando el dispositivo que recibió el token. |
iat | La hora a la que se emitió el token. |
exp | La hora a la que caduca el token. |
$ubicación
Una variable que se puede usar para hacer referencia a la clave de una $location
que se usó anteriormente en una estructura de reglas.
Cuando tiene una $location
en su estructura de reglas, puede usar una variable $
coincidente dentro de su expresión de regla para obtener el nombre del niño real que se está leyendo o escribiendo. Entonces supongamos que queremos darle a cada usuario acceso de lectura y escritura a su propia ubicación /users/<user>
. Podríamos usar:
{
"rules": {
"users": {
"$user": {
".read": "auth.uid === $user",
".write": "auth.uid === $user"
}
}
}
}
Cuando un cliente intenta acceder a /users/barney
, la ubicación predeterminada $user
coincidirá con $user
igual a "barney". Entonces la regla .read
verificará si auth.uid === 'barney'
. Como resultado, la lectura
será exitosa sólo si el cliente está autenticado con un uid de "barney"./users/barney
ahora
Contiene la cantidad de milisegundos desde la época de Unix según los servidores de Firebase Realtime Database.
La variable now
contiene la cantidad de milisegundos desde la época UNIX según los servidores de Firebase Realtime Database. Por ejemplo, podrías usar esto para validar que la hora created
de un usuario nunca se establezca en una hora futura:
{
"rules": {
"users": {
"$user": {
"created": {
".validate": "newData.val() < now"
}
}
}
}
}
raíz
Una RuleDataSnapshot correspondiente a los datos actuales en la raíz de su Firebase Realtime Database.
La variable raíz le proporciona una RuleDataSnapshot correspondiente a los datos actuales en la raíz de su Firebase Realtime Database. Puede usar esto para leer cualquier dato en su base de datos en sus expresiones de regla. Por ejemplo, si quisiéramos permitir a los usuarios leer /comments
solo si su /users/<id>/active
está configurado en verdadero, podríamos usar:
{
"rules": {
"comments": {
".read": "root.child('users').child(auth.uid).child('active').val() == true"
}
}
}
Entonces, si /users/barney/active
contenía el valor verdadero, un usuario autenticado con un uid de "barney" podría escribir en el nodo /comments
.
datos
Una RuleDataSnapshot correspondiente a los datos actuales en Firebase Realtime Database en la ubicación de la regla que se está ejecutando actualmente.
La variable de datos le proporciona una RuleDataSnapshot correspondiente a los datos actuales en la ubicación de la base de datos de la regla que se está ejecutando actualmente (a diferencia de root, que le proporciona los datos para la raíz de su base de datos).
Entonces, por ejemplo, si desea permitir que cualquier cliente acceda a /users/<user>
si /users/<user>/public
está configurado en verdadero, puede usar:
{
"rules": {
"users": {
"$user": {
".read": "data.child('public').val() == true"
}
}
}
}
La variable de datos está disponible en reglas .read
, .write
y .validate
.
nuevos datos
Un RuleDataSnapshot correspondiente a los datos que resultarán si se permite la escritura.
Para las reglas .write
y .validate
, la variable newData le proporciona una RuleDataSnapshot correspondiente a los datos que resultarán si se permite la escritura (es una "fusión" de los datos existentes más los nuevos datos que se están escribiendo). Entonces, si quisieras asegurarte de que cada usuario tenga un nombre y una edad, podrías usar:
{
"rules": {
"users": {
"$user": {
".read": true,
".write": true,
".validate": "newData.hasChildren(['name', 'age'])"
}
}
}
}
Dado que newData fusiona datos existentes y datos nuevos, se comporta correctamente incluso para actualizaciones "parciales". Por ejemplo:
var fredRef = firebase.database().ref("users/fred");
// Valid since we have a name and age.
fredRef.set({ name: "Fred", age: 19 });
// Valid since we are updating the name but there's already an age.
fredRef.child("age").set(27);
// Invalid since the .validate rule will no longer be true.
fredRef.child("name").remove();
La variable newData no está disponible en las reglas .read
ya que no se escriben datos nuevos. Sólo deberías usar datos .
RuleDataSnapshot: métodos
valor()
Obtiene el valor primitivo ( string
, number
, boolean
o null
) de este RuleDataSnapshot .
Valor de retorno : ( String
, Number
, Boolean
, Null
): el valor primitivo de esta RuleDataSnapshot .
A diferencia de DataSnapshot.val()
, llamar val()
en un RuleDataSnapshot que tiene datos secundarios no devolverá un objeto que contenga los elementos secundarios. En su lugar, devolverá un valor centinela especial. Esto garantiza que las reglas siempre puedan funcionar de manera extremadamente eficiente.
Como consecuencia, siempre debes usar child()
para acceder a los niños (por ejemplo data.child('name').val()
, no data.val().name
).
Este ejemplo solo permite la lectura si el elemento secundario isReadable está establecido en verdadero en la ubicación que se está leyendo.
".read": "data.child('isReadable').val() == true"
niño()
Obtiene un RuleDataSnapshot para la ubicación en la ruta relativa especificada.
Argumentos : childPath
String
: una ruta relativa a la ubicación de los datos secundarios.
Valor de retorno : RuleDataSnapshot
: RuleDataSnapshot para la ubicación secundaria.
La ruta relativa puede ser un simple nombre de niño (por ejemplo, 'fred') o una ruta más profunda separada por barras (por ejemplo, 'fred/nombre/primero'). Si la ubicación secundaria no tiene datos, se devuelve un RuleDataSnapshot vacío.
Este ejemplo solo permite la lectura si el elemento secundario isReadable está establecido en verdadero en la ubicación que se está leyendo.
".read": "data.child('isReadable').val() == true"
padre()
Obtiene una RuleDataSnapshot para la ubicación principal.
Valor de retorno : RuleDataSnapshot
: RuleDataSnapshot para la ubicación principal.
Si esta instancia hace referencia a la raíz de su Firebase Realtime Database, no tiene padre y parent()
fallará, lo que provocará que se omita la expresión de regla actual (como un error).
Este ejemplo solo permite la lectura si el hermano isReadable está configurado en verdadero.
".read": "data.parent().child('isReadable').val() == true"
tieneniño(rutaniño)
Devuelve verdadero si el hijo especificado existe.
Argumentos : childPath
String
: una ruta relativa a la ubicación de un niño potencial.
Valor de retorno : booleano : true
si existen datos en la ruta secundaria especificada; de lo contrario false
.
Este ejemplo solo permite escribir los datos si contienen un "nombre" secundario.
".validate": "newData.hasChild('name')"
tieneNiños([niños])
Comprueba la existencia de niños.
Argumentos : Array
children
opcional : una matriz de claves secundarias que deben existir.
Valor de retorno : Boolean
: true
si existen los hijos (especificados); de lo contrario false
.
Si no se proporcionan argumentos, devolverá verdadero si RuleDataSnapshot tiene hijos. Si se proporciona una matriz de nombres de niños, devolverá verdadero solo si todos los niños especificados existen en RuleDataSnapshot .
Este ejemplo solo permite escribir los datos si contienen uno o más hijos.
".validate": "newData.hasChildren()"
Este ejemplo solo permite escribir los datos si contienen niños de "nombre" y "edad".
".validate": "newData.hasChildren(['name', 'age'])"
existe()
Devuelve verdadero si este RuleDataSnapshot contiene datos.
Valor de retorno : Boolean
: true
si RuleDataSnapshot contiene datos; de lo contrario false
.
La función existe devuelve verdadero si este RuleDataSnapshot contiene datos. Es una función puramente de conveniencia ya que data.exists()
es equivalente a data.val() != null
.
Este ejemplo permite escribir en esta ubicación siempre que no existan datos.
".write": "!data.exists()"
obtenerPrioridad()
Obtiene la prioridad de los datos en RuleDataSnapshot .
Valor de retorno : ( String
, Number
, Null
): la prioridad de los datos en este RuleDataSnapshot .
Este ejemplo garantiza que los nuevos datos que se escriben tengan prioridad.
".validate": "newData.getPriority() != null"
es número()
Devuelve verdadero si este RuleDataSnapshot contiene un valor numérico.
Valor de retorno : Boolean
: true
si los datos son numéricos; de lo contrario false
.
Este ejemplo garantiza que los nuevos datos que se escriben tengan una "edad" secundaria con un valor numérico.
".validate": "newData.child('age').isNumber()"
esCadena()
Devuelve verdadero si este RuleDataSnapshot contiene un valor de cadena.
Valor de retorno : Boolean
- true
si los datos son una String
; de lo contrario false
.
Este ejemplo garantiza que los nuevos datos que se escriben tengan un "nombre" secundario con un valor de cadena.
".validate": "newData.child('name').isString()
es booleano()
Devuelve verdadero si este RuleDataSnapshot contiene un valor booleano.
Valor de retorno : Boolean
: true
si los datos son Boolean
; de lo contrario false
.
Este ejemplo garantiza que los nuevos datos que se escriben tengan un elemento secundario "activo" con un valor booleano.
".validate": "newData.child('active').isBoolean()"
Cadena: Propiedades
longitud
Devuelve la longitud de la cadena.
Valor de retorno : Number
: el número de caracteres de la cadena.
Este ejemplo requiere que la cadena tenga al menos 10 caracteres.
".validate": "newData.isString() && newData.val().length >= 10"
Cadena: Métodos
contiene (subcadena)
Devuelve verdadero si la cadena contiene la subcadena especificada.
Argumentos : substring
String
: una subcadena a buscar.
Valor de retorno : Boolean
: true
si la cadena contiene la subcadena especificada; de lo contrario false
.
Este ejemplo requiere que los datos sean una cadena que contenga "@".
".validate": "newData.isString() && newData.val().contains('@')"
comienza con (subcadena)
Devuelve verdadero si la cadena comienza con la subcadena especificada.
Argumentos : substring
String
: una subcadena que se buscará al principio.
Valor de retorno : Boolean
: true
si la cadena contiene la subcadena especificada; de lo contrario false
.
Este ejemplo permite acceso de lectura si auth.token.identifier
comienza con "internal-"
".read": "auth.token.identifier.beginsWith('internal-')"
termina con (subcadena)
Devuelve verdadero si la cadena termina con la subcadena especificada.
Argumentos : substring
String
: una subcadena que se buscará al final.
Valor de retorno : Boolean
: true
si la cadena termina con la subcadena especificada; de lo contrario false
.
Este ejemplo permite acceso de lectura si auth.token.identifier
termina en "@empresa.com"
".read": "auth.token.identifier.endsWith('@company.com')"
reemplazar (subcadena, reemplazo)
Devuelve una copia de la cadena con todas las instancias de una subcadena especificada reemplazadas por la cadena de reemplazo especificada.
Argumentos : substring String
: una subcadena a buscar. replacement String
: una cadena con la que reemplazar la subcadena.
Valor de retorno : String
: la nueva cadena después de reemplazar la subcadena con reemplazo.
El método replace()
difiere ligeramente del método replace()
de JavaScript en que reemplaza todas las instancias de una subcadena especificada con la cadena de reemplazo especificada, no solo la primera instancia.
Dado que no se permiten puntos en las claves, debemos escapar las cadenas con puntos antes de almacenarlas. Un ejemplo de esto sería con las direcciones de correo electrónico. Supongamos que tenemos una lista de direcciones de correo electrónico incluidas en la lista blanca en nuestro nodo /whitelist/
:
{
"user": {
"$uid": {
"email": <email>
}
},
"whitelist": {
"fred@gmail%2Ecom": true,
"barney@aol%2Ecom": true
}
}
Podemos crear una regla que solo permita agregar usuarios si su correo electrónico está en el nodo /whitelist/
:
{
"rules": {
"users": {
"$uid": {
".read": "true",
".write": "root.child('whitelist').child(newData.child('email').val().replace('.', '%2E')).exists()"
}
}
}
}
a minúsculas()
Devuelve una copia de la cadena convertida a minúsculas.
Valor de retorno : String
: la cadena convertida a minúsculas.
Este ejemplo permite acceso de lectura si auth.token.identifier
ya que todo está en minúsculas en /users
.
".read": "root.child('users').child(auth.token.identifier.toLowerCase()).exists()"
a mayúsculas()
Devuelve una copia de la cadena convertida a mayúsculas.
Valor de retorno : String
: la cadena convertida a mayúsculas.
Este ejemplo permite acceso de lectura si auth.token.identifier
ya que todas las mayúsculas existen en /users
.
".read": "root.child('users').child(auth.token.identifier.toUpperCase()).exists()"
coincidencias (expresión regular)
Devuelve verdadero si la cadena coincide con el literal de expresión regular especificado.
Valor de retorno : Boolean
: true
si la cadena coincide con la expresión regular literal, regex; de lo contrario false
.
Consulte la documentación completa de reglas de expresiones regulares .
Operadores
+ (añadir)
Se utiliza para agregar variables o para concatenación de cadenas.
El siguiente ejemplo garantiza que el nuevo valor incremente el valor existente exactamente en uno. Esto es útil para implementar un contador:
".write": "newData.val() === data.val() + 1"
".validate": "root.child('room_names/' + $room_id).exists()"
- (negar o restar)
Se utiliza para negar un valor o restar dos valores en una expresión de reglas.
Esta regla de validación verifica que el nuevo valor sea el inverso de un valor secundario en la ubicación:
".validate": "newData.val() === -(data.child('quantity').val())"
El siguiente ejemplo utiliza la resta para garantizar que solo se puedan leer los mensajes de los últimos diez minutos:
".read": "newData.child('timestamp').val() > (now - 600000)"
* (multiplicar)
Se utiliza para multiplicar variables en una expresión de reglas.
Esta regla de validación verifica si el nuevo valor es igual al producto de precio y cantidad (dos valores existentes):
".validate": "newData.val() === data.child('price').val() * data.child('quantity').val()"
/ (dividir)
Se utiliza para dividir variables en una expresión de reglas.
En el siguiente ejemplo, la regla de validación garantiza que los datos almacenados sean el promedio del total de datos almacenados en otro lugar:
".validate": "newData.val() === data.parent().child('sum').val() / data.parent().child('numItems').val()"
% (módulo)
Se utiliza para encontrar el resto de dividir una variable entre otra en una expresión de reglas.
Esta regla valida que sólo se pueden escribir números pares:
".validate": "newData.val() % 2 === 0"
=== (igual)
Se utiliza para comprobar si dos variables en una expresión de reglas tienen el mismo tipo y valor.
La siguiente regla utiliza el operador === para otorgar acceso de escritura solo al propietario de la cuenta de usuario. El uid del usuario debe coincidir exactamente con la clave ( $user_id
) para que la regla se evalúe como verdadera.
"users": {
".write": "$user_id === auth.uid"
}
!== (no es igual)
Se utiliza para comprobar si dos variables en una expresión de reglas no son iguales.
La siguiente regla de lectura garantiza que solo los usuarios que hayan iniciado sesión puedan leer los datos:
".read": "auth !== null"
&& (Y)
Se evalúa como verdadero si ambos operandos son verdaderos. Se utiliza para evaluar múltiples condiciones en una expresión de reglas.
La siguiente regla de validación verifica que los nuevos datos sean una cadena de menos de 100 caracteres:
".validate": "newData.isString() && newData.val().length < 100"
|| (O)
Se evalúa como verdadero si un operando en la expresión de reglas es verdadero.
En este ejemplo, podemos escribir siempre que no existan datos antiguos o nuevos. En otras palabras, podemos escribir si estamos eliminando o creando datos, pero no actualizando datos.
".write": "!data.exists() || !newData.exists()"
! (NO)
Se evalúa como verdadero si su único operando es falso. En expresiones de reglas, el ! El operador se utiliza a menudo para ver si se han escrito datos en una ubicación.
La siguiente regla solo permite acceso de escritura si no hay datos en la ubicación especificada:
".write": "!data.exists()"
> (mayor que)
Se utiliza para comprobar si un valor es mayor que otro valor en una expresión de reglas.
Esta regla de validación verifica que la cadena que se escribe no sea una cadena vacía:
".validate": "newData.isString() && newData.val().length > 0"
< (menos que)
Se utiliza para comprobar si un valor es menor que otro valor en una expresión de reglas.
Esta regla de validación verifica que una cadena tenga menos de 20 caracteres:
".validate": "newData.isString() && newData.val().length < 20"
>= (mayor o igual a)
Se utiliza para comprobar si un valor es mayor o igual que otro valor en una expresión de reglas.
Esta regla de validación verifica que la cadena que se escribe no sea una cadena vacía:
".validate": "newData.isString() && newData.val().length >= 1"
<= (menor o igual a)
Se utiliza para comprobar si un valor es menor o igual que otro valor en una expresión de reglas.
Esta regla de validación garantiza que no se puedan agregar nuevos datos en el futuro:
".validate": "newData.val() <= now"
? (operador ternario)
Se utiliza para evaluar una expresión de reglas condicionales.
El operador ternario toma tres operandos. ¿El operando antes del? es la condición. Si la condición se evalúa como verdadera, se evalúa el segundo operando. Si la condición es falsa, se evalúa el tercer operando.
Para la siguiente regla de validación, el nuevo valor puede ser un número o un valor booleano. Si es un número, debe ser mayor que 0.
".validate": "newData.isNumber() ? newData.val() > 0 : newData.isBoolean()"