Aprende a proteger archivos

Cloud Storage proporciona un modelo de seguridad declarativa basado en rutas de acceso, llamado reglas de seguridad de Firebase para Cloud Storage, que te permite proteger tus archivos de manera fácil y rápida.

Comprende las reglas

Las reglas de seguridad de Firebase para Cloud Storage se usan a fin de determinar quién tiene acceso de lectura y escritura a los archivos almacenados en Cloud Storage, cómo se estructuran los archivos y qué metadatos contienen. El tipo básico de regla es la regla allow, que permite solicitudes read y write si se especifica una condición opcional. Por ejemplo:

// If no condition is specified, the rule evaluates to true
allow read;

// Rules can optionally specify a condition
allow write: if <condition>;

// Rules can also specify multiple request methods
allow read, write: if <condition>;

Rutas de acceso coincidentes

Las reglas de seguridad de Storage usan match en las rutas de acceso de los archivos en Cloud Storage. Las reglas pueden usar match en las rutas de acceso exactas o comodines, y también pueden anidarse. Si ninguna regla de coincidencia permite un método de solicitud o la condición se evalúa como false, la solicitud se rechaza.

Coincidencias exactas

// Exact match for "images/profilePhoto.png"
match /images/profilePhoto.png {
  allow write: if <condition>;
}

// Exact match for "images/croppedProfilePhoto.png"
match /images/croppedProfilePhoto.png {
  allow write: if <other_condition>;
}

Coincidencias anidadas

// Partial match for files that start with "images"
match /images {
  // Exact match for "images/profilePhoto.png"
  match /profilePhoto.png {
    allow write: if <condition>;
  }

  // Exact match for "images/croppedProfilePhoto.png"
  match /croppedProfilePhoto.png {
    allow write: if <other_condition>;
  }
}

Coincidencias con comodín

Las reglas también se pueden usar para aplicar match a un patrón con comodines. Un comodín es una variable con nombre que representa una sola string, como profilePhoto.png, o varios segmentos de ruta, como images/profilePhoto.png.

Para crear un comodín, se encierra el nombre del comodín entre llaves (p. ej., {string}). Para declarar un comodín de varios segmentos, se agrega =** al nombre del comodín, como {path=**}:

// Partial match for files that start with "images"
match /images {
  // Exact match for "images/*"
  // e.g. images/profilePhoto.png is matched
  match /{imageId} {
    // This rule only matches a single path segment (*)
    // imageId is a string that contains the specific segment matched
    allow read: if <condition>;
  }

  // Exact match for "images/**"
  // e.g. images/users/user:12345/profilePhoto.png is matched
  // images/profilePhoto.png is also matched!
  match /{allImages=**} {
    // This rule matches one or more path segments (**)
    // allImages is a path that contains all segments matched
    allow read: if <other_condition>;
  }
}

Si varias reglas coinciden con un archivo, se usa un operador OR para determinar el resultado de todas las reglas evaluadas. Es decir, si alguna de las reglas con las que coincide el archivo se evalúa como true, el resultado es true.

En las reglas anteriores, se puede leer el archivo "images/profilePhoto.png" si condition o other_condition se evalúan como verdaderos, mientras que el archivo "images/users/user:12345/profilePhoto.png" solo está sujeto al resultado de other_condition.

Se puede hacer referencia a una variable comodín en match para proporcionar autorización de ruta de acceso o nombre de archivo:

// Another way to restrict the name of a file
match /images/{imageId} {
  allow read: if imageId == "profilePhoto.png";
}

Las reglas de seguridad de Storage no se transmiten en cascada y solo se evalúan cuando la ruta de acceso de la solicitud coincide con una ruta de acceso para la que se especificaron reglas.

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. La variable request contiene la ruta de acceso al archivo en la que se realiza la solicitud, el momento en que se recibe la solicitud y el valor resource nuevo, si la solicitud es una escritura. También se incluyen el estado de autenticación y los encabezados HTTP.

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 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 GCS de este objeto.
metageneration int La metageneración de objeto GCS 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.

Ejemplo completo

A modo de revisión general, puedes crear un ejemplo completo de reglas para una solución de almacenamiento de imágenes:

service firebase.storage {
 match /b/{bucket}/o {
   match /images {
     // Cascade read to any image type at any path
     match /{allImages=**} {
       allow read;
     }

     // Allow write files to the path "images/*", subject to the constraints:
     // 1) File is less than 5MB
     // 2) Content type is an image
     // 3) Uploaded content type matches existing content type (if it exists)
     // 4) File name (stored in imageId wildcard variable) is less than 32 characters
     match /{imageId} {
       allow write: if request.resource.size < 5 * 1024 * 1024
                    && request.resource.contentType.matches('image/.*')
                    && (resource == null || request.resource.contentType == resource.contentType)
                    && imageId.size() < 32
     }
   }
 }
}

Ahora, integremos Firebase Authentication para obtener datos detallados del acceso a archivos por usuario en la sección Seguridad del usuario.