CORS, intercambio de recursos de origen cruzado

Una introducción al intercambio de recursos entre orígenes, la forma de permitir que los clientes y los servidores se comuniquen incluso si no están en el mismo dominio

Una aplicación JavaScript que se ejecuta en el navegador generalmente solo puede acceder a recursos HTTP en el mismo dominio (origen) que la sirve.

La carga de imágenes o scripts / estilos siempre funciona, peroXHRyHa podido recuperarlas llamadas a otro servidor fallarán, a menos que ese servidor implemente una forma de permitir esa conexión.

Esta forma se llama CORS,Uso compartido de recursos de origen cruzado.

También cargando fuentes web usando@font-facetiene una política del mismo origen por defecto, y otras cosas menos populares (como texturas WebGL ydrawImagerecursos cargados en la API Canvas).

Una cosa muy importante que necesita CORS esMódulos ES, introducido recientemente en los navegadores modernos.

Si no configura una política CORSen el servidorque permite servir orígenes de terceros, la solicitud fallará.

Obtener ejemplo:

Fetch failed because of CORS policy

Ejemplo de XHR:

XHR request failed because of CORS policy

Un recurso de origen cruzado falla si:

  • a un diferentedominio
  • a un diferentesubdominio
  • a un diferentePuerto
  • a un diferenteprotocolo

y está ahí para su seguridad, para evitar que usuarios malintencionados se aprovechen de laPlataforma web.

Pero si controlas tanto el servidor como el cliente, tienes todas las buenas razones para permitirles hablar entre ellos.

¿Cómo?

Depende de su pila del lado del servidor.

Soporte de navegador

Bastante bien (básicamente todos excepto IE <10):

CORS browser support

Ejemplo con Express

Si está utilizando Node.js y Express como marco, utilice elPaquete de middleware CORS.

Aquí hay una implementación simple de un ExpressNode.jsservidor:

const express = require('express')
const app = express()

app.get(’/without-cors’, (req, res, next) => { res.json({ msg: ‘😞 no CORS, no party!’ }) })

const server = app.listen(3000, () => { console.log(‘Listening on port %s’, server.address().port) })

Si golpeas/without-corscon una solicitud de recuperación de un origen diferente, va a plantear el problema de CORS.

Todo lo que necesita hacer para que las cosas funcionen es requerir elcorspaquete vinculado anteriormente y pasarlo como una función de middleware a un controlador de solicitud de punto final:

const express = require('express')
const cors = require('cors')
const app = express()

app.get(’/with-cors’, cors(), (req, res, next) => { res.json({ msg: ‘WHOAH with CORS it works! 🔝 🎉’ }) })

/* the rest of the app */

Hice un ejemplo simple de Glitch, aquí está su código:https://glitch.com/edit/#!/flavio-cors-client.

Este es el servidor Node.js Express:https://glitch.com/edit/#!/flaviocopes-cors-example-express

Observe cómo se sigue recibiendo la solicitud que falla porque no maneja los encabezados CORS correctamente, como puede ver en el panel Red, donde se encuentra el mensaje que envió el servidor:

No response from CORS

Permitir solo orígenes específicos

Sin embargo, este ejemplo tiene un problema: el servidor aceptará CUALQUIER solicitud como origen cruzado.

Como puede ver en el panel Red, la solicitud que pasó tiene un encabezado de respuestaaccess-control-allow-origin: *:

The CORS response header

Debe configurar el servidor para permitir que solo un origen sirva y bloquear todos los demás.

Usando el mismocorsBiblioteca de nodo, así es como lo haría:

const cors = require('cors')

const corsOptions = { origin: https://yourdomain.com, }

app.get(’/products/:id’, cors(corsOptions), (req, res, next) => { //… })

También puedes servir más:

const whitelist = ['http://example1.com', 'http://example2.com']
const corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  },
}

Preflight

Hay algunas solicitudes que se manejan de forma “sencilla”. TodosGETlas solicitudes pertenecen a este grupo.

tambiénalgunos POSTyHEADlas solicitudes también lo hacen.

POSTlas solicitudes también están en este grupo, si satisfacen el requisito de utilizar un tipo de contenido de

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

Todas las demás solicitudes deben pasar por una fase de aprobación previa, llamada verificación previa. El navegador hace esto para determinar si tiene permiso para realizar una acción, emitiendo unOPTIONSpetición.

Una solicitud de verificación previa contiene algunos encabezados que el servidor utilizará para verificar los permisos (se omiten los campos irrelevantes):

OPTIONS /the/resource/you/request
Access-Control-Request-Method: POST
Access-Control-Request-Headers: origin, x-requested-with, accept
Origin: https://your-origin.com

The server will respond with something like this(irrelevant fields omitted):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://your-origin.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE

We checked for POST, but the server tells us we can also issue other HTTP request types for that particular resource.

Following the Node.js Express example above, the server must also handle the OPTIONS request:

var express = require('express')
var cors = require('cors')
var app = express()

//allow OPTIONS on just one resource app.options(’/the/resource/you/request’, cors())

//allow OPTIONS on all resources app.options(’*’, cors())


More browser tutorials: