Condiciones de uso en las reglas de seguridad de almacenamiento en la nube de Firebase

Esta guía se basa en el aprendizaje de la sintaxis principal de la guía de lenguaje de reglas de seguridad de Firebase para mostrar cómo agregar condiciones a sus reglas de seguridad de Firebase para almacenamiento en la nube.

El componente principal de las reglas de seguridad de almacenamiento en la nube es la condición . Una condición es una expresión booleana que determina si se debe permitir o denegar una operación en particular. Para las reglas básicas, el uso de literales true y false como condiciones funciona perfectamente bien. Pero el lenguaje Reglas de seguridad de Firebase para almacenamiento en la nube le brinda formas de escribir condiciones más complejas que pueden:

  • Comprobar la autenticación de usuario
  • Validar datos entrantes

Autenticación

Firebase Security Rules for Cloud Storage se integra con Firebase Authentication para proporcionar una potente autenticación basada en usuarios para Cloud Storage. Esto permite un control de acceso granular basado en reclamos de un token de autenticación de Firebase.

Cuando un usuario autenticado realiza una solicitud en Cloud Storage, la variable request.auth se completa con el uid del usuario ( request.auth.uid ), así como con los reclamos de Firebase Authentication JWT ( request.auth.token ).

Además, cuando se utiliza la autenticación personalizada, se muestran notificaciones adicionales en el campo request.auth.token .

Cuando un usuario no autenticado realiza una solicitud, la variable request.auth es null .

Con estos datos, existen varias formas comunes de usar la autenticación para proteger los archivos:

  • Público: ignorar request.auth
  • Privado autenticado: verifique que request.auth no sea null
  • Usuario privado: verifique que request.auth.uid igual a un uid de ruta
  • Grupo privado: verifique que los reclamos del token personalizado coincidan con un reclamo elegido, o lea los metadatos del archivo para ver si existe un campo de metadatos

Público

Cualquier regla que no considere el contexto request.auth puede considerarse 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 activos de juegos, archivos de sonido u otro contenido estático.

// 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 posible que desee que los datos sean visibles para todos los usuarios autenticados de su aplicación, pero no para los usuarios no autenticados. Dado que la variable request.auth es null para todos los usuarios no autenticados, todo lo que tiene que hacer es comprobar que existe la variable request.auth para solicitar la autenticación:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

usuario privado

Con mucho, el caso de uso más común para request.auth será proporcionar a los usuarios individuales permisos granulares en sus archivos: desde cargar imágenes de perfil hasta leer documentos privados.

Dado que los archivos en Cloud Storage tienen una "ruta" completa al archivo, todo lo que se necesita para hacer que un archivo sea controlado por un usuario es una pieza de información de identificación de usuario única en el prefijo del nombre de archivo (como el uid del usuario) que se puede verificar cuando se evalúa 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á permitir permisos de grupo en un objeto, como permitir que varios miembros del equipo colaboren en un documento compartido. Hay varios enfoques para hacer esto:

  • Acumule un token personalizado de autenticación de Firebase que contenga información adicional sobre un miembro del grupo (como una ID de grupo)
  • Incluir información del grupo (como un ID de grupo o una lista de uid autorizados) en los metadatos del archivo

Una vez que estos datos se almacenan en el token o en los metadatos del archivo, 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;
}

Solicitar Evaluación

Las cargas, descargas, cambios de metadatos y eliminaciones se evalúan mediante la request enviada a Cloud Storage. Además de la identificación única del usuario y la carga de autenticación de Firebase en el objeto request.auth como se describe anteriormente, la variable de request contiene la ruta del archivo donde se realiza la solicitud, la hora en que se recibe la solicitud y el nuevo valor del resource si la solicitud es una escritura. También se incluyen los encabezados HTTP y el estado de autenticación.

El objeto de request también contiene la identificación única 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 los documentos.

Una lista completa de propiedades en el objeto de request está disponible a continuación:

Propiedad Escribe Descripción
auth mapa<cadena, cadena> Cuando un usuario inicia sesión, proporciona uid , la identificación única del usuario y token , un mapa de reclamos de Firebase Authentication JWT. De lo contrario, será null .
params mapa<cadena, cadena> Mapa que contiene los parámetros de consulta de la solicitud.
path sendero Una path representa la ruta en la que se está realizando la solicitud.
resource mapa<cadena, cadena> El nuevo valor del recurso, presente solo en las solicitudes de write .
time marca de tiempo Una marca de tiempo que representa la hora del servidor en la que se evalúa la solicitud.

Evaluación de recursos

Al evaluar las reglas, es posible que también desee evaluar los metadatos del archivo que se está cargando, descargando, modificando o eliminando. Esto le permite crear reglas complejas y poderosas que hacen cosas como permitir que solo se carguen archivos con ciertos tipos de contenido, o que solo se eliminen archivos que superen cierto tamaño.

Firebase Security Rules for Cloud Storage proporciona metadatos de archivo en el objeto de resource , que contiene pares clave/valor de los metadatos que aparecen en un objeto de Cloud Storage. Estas propiedades se pueden inspeccionar en solicitudes de read o write para garantizar la integridad de los datos.

En solicitudes de write (como cargas, actualizaciones de metadatos y eliminaciones), además del objeto de resource , que contiene metadatos de archivo para el archivo que existe actualmente en la ruta de la solicitud, también tiene la capacidad de usar el objeto request.resource , que contiene un subconjunto de los metadatos del archivo que se escribirán si se permite la escritura. Puede 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 del archivo.

Una lista completa de propiedades en el objeto de resource está disponible a continuación:

Propiedad Escribe Descripción
name cuerda El nombre completo del objeto.
bucket cuerda El nombre del depósito en el que reside este objeto.
generation En t La generación de objetos de Google Cloud Storage de este objeto.
metageneration En t La metageneración del objeto Google Cloud Storage de este objeto.
size En t El tamaño del objeto en bytes.
timeCreated marca de tiempo Una marca de tiempo que representa la hora en que se creó un objeto.
updated marca de tiempo Una marca de tiempo que representa la hora en que se actualizó por última vez un objeto.
md5Hash cuerda Un hash MD5 del objeto.
crc32c cuerda Un hash crc32c del objeto.
etag cuerda El etag asociado con este objeto.
contentDisposition cuerda La disposición de contenido asociada a este objeto.
contentEncoding cuerda La codificación de contenido asociada con este objeto.
contentLanguage cuerda El idioma del contenido asociado con este objeto.
contentType cuerda El tipo de contenido asociado con este objeto.
metadata mapa<cadena, cadena> Pares clave/valor de metadatos personalizados adicionales especificados por el desarrollador.

request.resource contiene todos estos a excepción de generation , metageneration , etag , timeCreated y updated .

Validar datos

Las reglas de seguridad de Firebase para almacenamiento en la nube también se pueden usar para la validación de datos, incluida la validación del nombre y la ruta del archivo, así como las propiedades de los metadatos del archivo, como el tipo de contentType y el 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 sus reglas de seguridad de Firebase se vuelven más complejas, es posible que desee incluir conjuntos de condiciones en funciones que pueda reutilizar en su conjunto de reglas. Las reglas de seguridad admiten funciones personalizadas. La sintaxis de las funciones personalizadas es un poco como JavaScript, pero las funciones de las reglas de seguridad de Firebase están escritas en un lenguaje específico del dominio que tiene algunas limitaciones importantes:

  • Las funciones pueden contener solo una sola declaración de return . No pueden contener ninguna 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 ámbito en el que están definidas. Por ejemplo, una función definida dentro del alcance del service firebase.storage tiene acceso a la variable de resource y, solo para Cloud Firestore, funciones integradas como get() y exists() .
  • Las funciones pueden llamar a otras funciones pero no pueden repetirse. La profundidad total de la pila de llamadas está limitada a 10.
  • En las reglas de rules2 , las funciones pueden definir variables usando la palabra clave let . Las funciones pueden tener cualquier número de enlaces let, pero deben terminar con una declaración de retorno.

Una función se define con la palabra clave function y toma cero o más argumentos. Por ejemplo, es posible que desee combinar los dos tipos de condiciones utilizadas en los ejemplos anteriores en una sola 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();
    }
  }
}

El uso de funciones en sus reglas de seguridad de Firebase las hace más fáciles de mantener a medida que crece la complejidad de sus reglas.

Próximos pasos

Después de esta discusión de las condiciones, tiene una comprensión más sofisticada de las Reglas y está listo para:

Aprenda a manejar los casos de uso principales y aprenda el flujo de trabajo para desarrollar, probar e implementar reglas: