Uso compartido de recursos entre dominios (CORS)

Comparte recursos de origen cruzado de forma segura

Mariko Kosaka

La política del 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 impide los usos legítimos.

A menudo, las apps web modernas quieren 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 deben estar disponibles para que cualquier persona 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) corrige 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
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 mediante el Protocolo de transferencia de hipertexto (HTTP). HTTP define las reglas de comunicación entre el solicitante y la persona que responde, 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 o la codificación del mensaje. Un encabezado puede incluir una gran variedad de información que se expresa como pares clave-valor. El encabezado de la solicitud y el de respuesta contienen información diferente.

Encabezado de la solicitud de muestra

Accept: text/html
Cookie: Version=1

Este encabezado equivale a decir "Quiero recibir HTML como respuesta. Esta es una galleta 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. No almacenar esto en caché".

Body

El mensaje en sí Puede ser texto sin formato, un objeto 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 de origen cruzado. Cuando necesitas un recurso público de un origen diferente, el servidor que proporciona los recursos 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 de 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 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 respuesta con el sitio del cliente.

Comparte credenciales con CORS

Por motivos de privacidad, CORS suele usarse 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 debe establecerse en un origen específico (sin comodín mediante *) y Access-Control-Allow-Credentials debe configurarse como true.

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

Solicitudes preliminares 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 que no sean Accept, Accept-Language ni Content-Language.
  • Una solicitud que tiene un encabezado Content-Type distinto de application/x-www-form-urlencoded, multipart/form-data o text/plain.

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

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 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 a fin de almacenar en caché los resultados de las comprobaciones preliminares. Esto permite que el cliente envíe varias solicitudes complejas sin necesidad de repetir la solicitud de comprobación previa.