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 impide 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 usos legítimos.

Las apps web modernas suelen querer 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>. 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 usaron soluciones alternativas, como JSONP.

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

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

solicitud y respuesta
Se ilustran 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 servidor, 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.

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

Ejemplo de encabezado de solicitud

Accept: text/html
Cookie: Version=1

Este encabezado equivale a decir "Quiero recibir HTML en la respuesta. Aquí tienes una galleta".

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". No almacenes esto en caché".

Cuerpo

Es 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 recuerda eso 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, el navegador agrega un encabezado Origin con el origen actual (esquema, host y puerto).

Paso 2: Respuesta del servidor

Cuando un servidor ve este encabezado y quiere 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 cliente.

Comparte credenciales con CORS

Por motivos de privacidad, CORS se suele usar para solicitudes anónimas, en las que no se identifica al solicitante. Si deseas enviar cookies cuando usas CORS, que pueden 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 debe establecerse en un origen específico (sin comodines con *) y Access-Control-Allow-Credentials debe establecerse 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:

  • Una solicitud que usa métodos distintos de GET, POST o HEAD.
  • Una solicitud que incluye encabezados distintos de Accept, Accept-Language o 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 preliminares necesarias y las envían antes del mensaje de solicitud real. La solicitud preliminar es una solicitud de OPTIONS como la del siguiente ejemplo:

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

En el lado del servidor, la app que recibe la solicitud responde a la solicitud preliminar con información sobre los métodos que la aplicación acepta desde 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 durante la que se almacenarán en caché los resultados preliminares. Esto permite que el cliente envíe varias solicitudes complejas sin necesidad de repetir la solicitud preliminar.