Esta guía complementa el artículo sobre la sintaxis principal del lenguaje de Firebase Security Rules. Aquí aprenderás a agregar condiciones a tu Firebase Security Rules para Cloud Storage.
El componente básico principal de Cloud Storage Security Rules es la condición. Una condición es una expresión booleana que determina si se debe permitir o rechazar una operación en particular. Para reglas básicas, el uso de literales de true
y false
como condiciones funciona de manera correcta. Sin embargo, el lenguaje de Firebase Security Rules para Cloud Storagete brinda diferentes maneras de escribir condiciones más complejas que pueden realizar las siguientes acciones:
- Verificar la autenticación de los usuarios
- Validar los datos entrantes
Autenticación
Firebase Security Rules para Cloud Storage se integra con Firebase Authentication para proporcionar autenticación potente basada en usuarios para Cloud Storage. Esto permite un control detallado del acceso en función de las reclamaciones de un token Firebase Authentication.
Cuando un usuario autenticado realiza una solicitud a Cloud Storage, la variable request.auth
se propaga con el uid
del usuario (request.auth.uid
), al igual que las reclamaciones de JWT Firebase Authentication (request.auth.token
).
Además, cuando se utiliza la autenticación personalizada, las reclamaciones adicionales se muestran en el campo request.auth.token
.
Cuando un usuario no autenticado realiza una solicitud, la variable request.auth
es null
.
Si usas estos datos, existen varias formas comunes en las que puedes usar la autenticación para proteger archivos:
- Público: Ignora
request.auth
. - Privado autenticado: Comprueba que
request.auth
no seanull
. - Usuario privado: Comprueba que
request.auth.uid
sea igual aluid
de una ruta. - Grupo privado: Comprueba que las reclamaciones del token personalizado coincidan con una reclamación elegida o lee los metadatos de archivos para ver si existe un campo de metadatos.
Público
Cualquier regla que omita el contexto request.auth
puede considerarse como una regla public
, ya que no considera el contexto de autenticación del usuario.
Estas reglas pueden ser útiles para mostrar datos públicos como elementos de juegos, archivos de sonido
o contenido estático de otro tipo.
// Anyone to read a public image if the file is less than 100kB // Anyone can upload a public file ending in '.txt' match /public/{imageId} { allow read: if resource.size < 100 * 1024; allow write: if imageId.matches(".*\\.txt"); }
Privado autenticado
En ciertos casos, es necesario que todos los usuarios autenticados en tu aplicación puedan ver datos, pero no así los usuarios no autenticados. Dado que la variable request.auth
es null
para todos los usuarios no autenticados, lo único que debes hacer es comprobar que la variable request.auth
existe, a fin de requerir la autenticación:
// Require authentication on all internal image reads match /internal/{imageId} { allow read: if request.auth != null; }
Usuario privado
Sin duda, el caso de uso más común de request.auth
será otorgar permisos detallados a los archivos de cada usuario: desde la carga de fotos de perfil hasta la lectura de documentos privados.
Dado que los archivos almacenados en Cloud Storage tienen una “ruta de acceso” completa al archivo, todo lo que se requiere para que un usuario pueda controlar un archivo es información de identificación exclusiva que identifique al usuario en el prefijo del nombre del archivo (como el uid
del usuario) que se puede verificar cuando se evalúe la regla:
// Only a user can upload their profile picture, but anyone can view it match /users/{userId}/profilePicture.png { allow read; allow write: if request.auth.uid == userId; }
Grupo privado
Otro caso de uso igualmente común será otorgar permisos de grupo en un objeto, como permitir que varios miembros de un equipo colaboren en un documento compartido. Existen varias maneras de hacer esto:
- Crear un token personalizado de Firebase Authentication que contenga información adicional sobre un miembro del grupo (como el ID del grupo)
- Incluir información del grupo (como su ID o una lista de
uid
autorizados) en los metadatos del archivo
Una vez que se almacenan esos datos en el token o en los metadatos de archivos, se puede hacer referencia a ellos desde una regla:
// Allow reads if the group ID in your token matches the file metadata's `owner` property // Allow writes if the group ID is in the user's custom token match /files/{groupId}/{fileName} { allow read: if resource.metadata.owner == request.auth.token.groupId; allow write: if request.auth.token.groupId == groupId; }
Evaluación de solicitudes
Las cargas, las descargas, los cambios de metadatos y las eliminaciones se evalúan con la request
enviada a Cloud Storage. Además del ID único del usuario y la carga útil de Firebase Authentication en el objeto request.auth
, como se describió antes, la variable request
contiene la ruta de acceso del archivo en la que se realiza la solicitud, el momento en que se recibe la solicitud y el nuevo valor de resource
si la solicitud es una operación de escritura.
El objeto request
también contiene el ID único del usuario y la carga útil de Firebase Authentication en el objeto request.auth
, que se explicará con más detalle en la sección Seguridad basada en el usuario de la documentación.
A continuación, se muestra una lista completa de las propiedades del objeto request
:
Propiedad | Tipo | Descripción |
---|---|---|
auth |
mapa <string, string> | Cuando un usuario accede, proporciona el uid , el ID único del usuario y token , un mapa de las reclamaciones de Firebase Authentication JWT. De lo contrario, será null . |
params |
mapa <string, string> | Un mapa que contiene los parámetros de consulta de la solicitud. |
path |
path | Un objeto path que representa la ruta en la que se realiza la solicitud. |
resource |
mapa <string, string> | El nuevo valor del recurso, presente solo en solicitudes de tipo write . |
time |
timestamp | Una marca de tiempo que representa la hora del servidor a la que se evalúa la solicitud. |
Evaluación de recursos
Para la evaluación de reglas, te recomendamos que también evalúes los metadatos del archivo que se va a subir, descargar, modificar o borrar. Esto te permite crear reglas complejas y potentes que ejecutan tareas como permitir que se suban archivos con ciertos tipos de contenido solamente o que solo se borren los archivos que superen cierto tamaño.
Firebase Security Rules para Cloud Storage proporciona metadatos de archivos en resource
, que contiene pares clave-valor de los metadatos que se muestran en un objeto de Cloud Storage. Estas propiedades se pueden inspeccionar en solicitudes read
o write
para garantizar la integridad de los datos.
En las solicitudes write
(como cargas, actualizaciones de metadatos y eliminaciones), además del objeto resource
, que contiene metadatos de archivo para el archivo que existe actualmente en la ruta de la solicitud, también puedes usar el objeto request.resource
, que contiene un subconjunto de los metadatos del archivo que se escribirán si se permite la escritura. Puedes usar estos dos valores para garantizar la integridad de los datos o hacer cumplir las restricciones de la aplicación, como el tipo o el tamaño de los archivos.
A continuación, se muestra una lista completa de las propiedades del objeto resource
:
Propiedad | Tipo | Descripción |
---|---|---|
name |
string | El nombre completo del objeto. |
bucket |
string | El nombre del depósito en el que reside el objeto. |
generation |
int | La generación de objeto de Google Cloud Storage de este objeto. |
metageneration |
int | La metageneración de objeto de Google Cloud Storage de este objeto. |
size |
int | El tamaño del objeto en bytes. |
timeCreated |
timestamp | Una marca de tiempo que representa la hora a la que se creó el objeto. |
updated |
timestamp | Una marca de tiempo que representa la hora a la que se actualizó el objeto por última vez. |
md5Hash |
string | Un hash MD5 del objeto. |
crc32c |
string | Un hash crc32c del objeto. |
etag |
string | La etag asociada con este objeto. |
contentDisposition |
string | La disposición de contenido asociada con este objeto. |
contentEncoding |
string | La codificación de contenido asociada con este objeto. |
contentLanguage |
string | El idioma del contenido asociado con este objeto. |
contentType |
string | El tipo de contenido asociado con este objeto. |
metadata |
mapa <string, string> | Pares clave-valor de los metadatos personalizados adicionales que especifica el desarrollador. |
request.resource
contiene todas ellas, excepto generation
, metageneration
, etag
, timeCreated
y updated
.
Mejora con Cloud Firestore
Puedes acceder a documentos en Cloud Firestore para evaluar otras autorizaciones con tus criterios.
Con las funciones firestore.get()
y firestore.exists()
, tus reglas de seguridad pueden evaluar las solicitudes entrantes en comparación con los documentos de Cloud Firestore.
Las funciones firestore.get()
y firestore.exists()
usan rutas de acceso a documentos especificadas por completo. Cuando usas variables a fin de construir rutas de acceso para firestore.get()
y firestore.exists()
, debes escapar las variables de forma explícita con la sintaxis $(variable)
.
En el siguiente ejemplo, vemos una regla que restringe el acceso de lectura a los archivos para los usuarios que son miembros de clubes en particular.
service firebase.storage { match /b/{bucket}/o { match /users/{club}/files/{fileId} { allow read: if club in firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships } } }
service firebase.storage { match /b/{bucket}/o { match /users/{userId}/photos/{fileId} { allow read: if firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id)) } } }
Una vez que crees y guardes tus primeros Cloud Storage Security Rules que usan estas funciones de Cloud Firestore se te solicitará en la consola de Firebase o en la CLI de Firebase que realices para habilitar los permisos para conectar los dos productos.
Puedes inhabilitar la función quitando un rol de IAM, como se describe en Implementa y administra Firebase Security Rules.
Valida datos
Firebase Security Rules para Cloud Storage también se puede usar para la validación de datos, lo que incluye validar el nombre y la ruta del archivo, así como las propiedades de los metadatos del archivo, como contentType
y size
.
service firebase.storage { match /b/{bucket}/o { match /images/{imageId} { // Only allow uploads of any image file that's less than 5MB allow write: if request.resource.size < 5 * 1024 * 1024 && request.resource.contentType.matches('image/.*'); } } }
Funciones personalizadas
A medida que tus Firebase Security Rules 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 Firebase Security Rules se escriben en un lenguaje específico del dominio, que 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 permiso
service firebase.storage
tiene acceso a la variableresource
y, solo en Cloud Firestore, a 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 10.
- En la versión
rules2
, las funciones pueden definir variables con la palabra clavelet
. Las funciones pueden tener cualquier cantidad de vinculaciones let, pero deben terminar con una declaración de retorno.
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 firebase.storage {
match /b/{bucket}/o {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /images/{imageId} {
allow read, write: if signedInOrPublic();
}
match /mp3s/{mp3Ids} {
allow read: if signedInOrPublic();
}
}
}
Usar funciones en tu Firebase Security Rules hace que sean más fáciles de mantener debido a su complejidad de tus reglas crece.
Próximos pasos
Después de leer este artículo sobre las condiciones, comprenderás las reglas en más profundidad y podrás hacer lo siguiente:
Aprender a abordar los casos de uso principales y conocer el flujo de trabajo para desarrollar, probar e implementar reglas
- Escribe reglas que aborden casos comunes.
- Para complementar tus conocimientos, revisa las situaciones en las que debes detectar y evitar reglas inseguras.
- Prueba las reglas con el emulador de Cloud Storage y la biblioteca dedicada de pruebas de reglas de seguridad.
- Revisa los métodos disponibles para implementar Rules.