Esta guía complementa el artículo sobre la sintaxis principal del lenguaje de reglas de seguridad de Firebase. Aquí aprenderás a agregar condiciones a tus reglas de seguridad de Firebase de Cloud Storage.
El elemento principal de las reglas de seguridad de Cloud Storage 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, las reglas de seguridad de Firebase para el lenguaje de Cloud Storage
te brindan diferentes maneras de escribir condiciones más complejas que pueden realizarse en los siguientes casos:
- Verificar la autenticación de los usuarios
- Validar los datos entrantes
Authentication
Las reglas de seguridad de Firebase para Cloud Storage se integran a Firebase Authentication para brindarte autenticación sólida basada en el usuario en Cloud Storage, lo cual permite controlar el acceso de forma detallada en función de las reclamaciones de un token de Firebase Authentication.
Cuando un usuario autenticado realiza una solicitud a Cloud Storage, la variable request.auth
se propaga con el uid
(request.auth.uid
) del usuario, al igual que las reclamaciones de los JWT de 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 acerca de 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 el request
enviado 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 JWT de Firebase Authentication. De lo contrario, será null . |
params |
mapa <string, string> | Un mapa que contiene los parámetros de consulta de la solicitud. |
path |
ruta | 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 |
marca de tiempo | 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.
Las reglas de seguridad de Firebase para Cloud Storage proporcionan metadatos de archivo en el objeto 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 |
marca de tiempo | Una marca de tiempo que representa la hora a la que se creó el objeto. |
updated |
marca de tiempo | 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
.
Cómo agregar mejoras con Cloud Firestore
Puedes acceder a documentos en Cloud Firestore para evaluar otros criterios de autorización.
Con las funciones firestore.get()
y firestore.exists()
, las 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 } } }En el siguiente ejemplo, solo los amigos de un usuario pueden ver sus fotos.
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 primeras reglas de seguridad de Cloud Storage que usan estas funciones de Cloud Firestore, se te pedirá que habilites los permisos para conectar los dos productos en Firebase console o Firebase CLI.
Puedes inhabilitar la función si quitas un rol de IAM, como se describe en Implementa y administra las reglas de seguridad de Firebase.
Valida datos
Las reglas de seguridad de Firebase para Cloud Storage también se pueden utilizar para la validación de datos, lo cual incluye la validación del nombre de archivo y la ruta de acceso, así como las propiedades de los metadatos de 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 reglas de seguridad de Firebase 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 de Firebase 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 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 hacen 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 las reglas de seguridad de Firebase las hace más fáciles de mantener a medida que aumenta la complejidad de las reglas.
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 reglas.