Uso compartido de recursos entre dominios (CORS)

Comparte recursos entre orígenes de forma segura

Mariko Kosaka

La política de mismo origen del navegador bloquea la lectura de un recurso de un origen diferente. Este mecanismo impide que los sitios maliciosos lean los datos de otros sitios, pero también evita los usos legítimos.

A menudo, las apps web modernas desean obtener recursos de un origen diferente, por ejemplo, recuperar datos JSON de un dominio diferente o cargar imágenes de otro sitio en un elemento <canvas>. Estos pueden ser recursos públicos que deberían estar disponibles para que cualquiera los lea, pero la política del mismo origen bloquea su uso. Históricamente, los desarrolladores han usado soluciones alternativas, como JSONP.

El uso compartido de recursos entre dominios (CORS) soluciona este problema de forma estandarizada. Habilitando CORS, el servidor le indica al navegador que puede usar un origen adicional.

¿Cómo funciona una solicitud de recursos en la Web?

solicitud y respuesta
Ilustración de la solicitud del cliente y la respuesta del servidor.

Un navegador y un servidor pueden intercambiar datos a través de la red con el protocolo de transferencia de hipertexto (HTTP). HTTP define las reglas de comunicación entre el solicitante y el responsable de la respuesta, incluida la información necesaria para obtener un recurso.

El encabezado HTTP negocia el intercambio de mensajes entre el cliente y el servidor, y se usa para determinar el acceso. Tanto la solicitud del navegador como el mensaje de respuesta del servidor se dividen en un encabezado y un cuerpo.

Información sobre el mensaje, como el tipo de mensaje o la codificación del mensaje Un encabezado puede incluir una variedad de información expresada como pares clave-valor. El encabezado de solicitud y el encabezado de respuesta contienen información diferente.

Encabezado de solicitud de muestra

Accept: text/html
Cookie: Version=1

Este encabezado equivale a decir "Quiero recibir HTML en respuesta. Esta es una cookie que tengo".

Encabezado de respuesta de muestra

Content-Encoding: gzip
Cache-Control: no-store

Este encabezado equivale a decir "Los datos de esta respuesta están codificados con gzip". Don't cache this".

Cuerpo

El mensaje en sí. Puede ser texto sin formato, un archivo binario de imagen, JSON, HTML o muchos otros formatos.

¿Cómo funciona CORS?

La política del mismo origen le indica al navegador que bloquee las solicitudes multiorigen. Cuando necesitas un recurso público de un origen diferente, el servidor que proporciona el recurso le indica al navegador que el origen que envía la solicitud puede acceder a su recurso. El navegador lo recuerda y permite el uso compartido de recursos entre dominios para ese recurso.

Paso 1: Solicitud del cliente (navegador)

Cuando el navegador realiza una solicitud de origen cruzado, agrega un encabezado Origin con el origen actual (esquema, host y puerto).

Paso 2: Respuesta del servidor

Cuando un servidor ve este encabezado y desea permitir el acceso, agrega un encabezado Access-Control-Allow-Origin a la respuesta que especifica el origen solicitante (o * para permitir cualquier origen).

Paso 3: El navegador recibe la respuesta

Cuando el navegador ve esta respuesta con un encabezado Access-Control-Allow-Origin adecuado, comparte los datos de la respuesta con el sitio del cliente.

Cómo compartir credenciales con CORS

Por motivos de privacidad, CORS se usa normalmente para solicitudes anónimas, en las que no se identifica al solicitante. Si deseas enviar cookies cuando usas CORS, que puede identificar al remitente, debes agregar encabezados adicionales a la solicitud y la respuesta.

Solicitud

Agrega credentials: 'include' a las opciones de recuperación como en el siguiente ejemplo. Esto incluye la cookie con la solicitud de la siguiente manera:

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})

Respuesta

Access-Control-Allow-Origin se debe establecer en un origen específico (sin comodines con *) y Access-Control-Allow-Credentials se debe establecer en true.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

Solicitudes de comprobación previa para llamadas HTTP complejas

Cuando una app web realiza una solicitud HTTP compleja, el navegador agrega una solicitud de comprobación previa al comienzo de la cadena de solicitudes.

La especificación de CORS define una solicitud compleja de la siguiente manera:

  • Es una solicitud que usa métodos distintos de GET, POST o HEAD.
  • Una solicitud que incluye encabezados que no son Accept, Accept-Language ni Content-Language
  • Una solicitud que tiene un encabezado Content-Type que no es application/x-www-form-urlencoded, multipart/form-data ni text/plain

Los navegadores crean automáticamente las solicitudes de verificación previa necesarias y las envían antes del mensaje de solicitud real. La solicitud de comprobación previa es una solicitud OPTIONS como la siguiente:

OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE

En el servidor, la app que recibe la solicitud responde a la solicitud de verificación preliminar con información sobre los métodos que la aplicación acepta de este origen:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS

La respuesta del servidor también puede incluir un encabezado Access-Control-Max-Age para especificar la duración en segundos para almacenar en caché los resultados de la verificación previa al vuelo. Esto permite que el cliente envíe varias solicitudes complejas sin necesidad de repetir la solicitud de verificación previa.