Pregunta ¿Cómo funciona el encabezado Access-Control-Allow-Origin?


Aparentemente, he entendido mal su semántica. Pensé en algo como esto:

  1. Un cliente descarga el código de JavaScript MyCode.js de http: // siteA - el origen.
  2. El encabezado de respuesta de MyCode.js contiene Access-Control-Allow-Origin: http: // siteB, lo que pensé que significaba que a MyCode.js se le permitía hacer referencias de origen cruzado al sitio B.
  3. El cliente activa alguna funcionalidad de MyCode.js, que a su vez realiza solicitudes a http: // siteB, lo que debería estar bien, a pesar de ser solicitudes de origen cruzado.

Bueno, estoy equivocado. No funciona así en absoluto. Entonces, he leído Intercambio de recursos de origen cruzado e intenté leer Intercambio de recursos de origen cruzado en la recomendación w3c

Una cosa es segura: todavía no entiendo cómo se supone que debo usar este encabezado.

Tengo el control total tanto del sitio A como del sitio B. ¿Cómo habilito el código javascript descargado del sitio A para acceder a los recursos en el sitio B usando este encabezado?

PD

No quiero utilizar JSONP.


787
2018-05-17 13:23


origen


Respuestas:


Access-Control-Allow-Origin es un Encabezado CORS (Intercambio de recursos de origen cruzado).

Cuando el Sitio A intenta recuperar contenido del Sitio B, el Sitio B puede enviar un Access-Control-Allow-Origin encabezado de respuesta para decirle al navegador que el contenido de esta página es accesible para ciertos orígenes. (Un origen es un dominio, más un esquema y número de puerto.) Por defecto, las páginas del Sitio B son no accesible a ningún otro origen; utilizando el Access-Control-Allow-Origin el encabezado abre una puerta para el acceso de origen cruzado por orígenes solicitantes específicos.

Para cada recurso / página que el Sitio B quiere hacer accesible al Sitio A, el Sitio B debe publicar sus páginas con el encabezado de respuesta:

Access-Control-Allow-Origin: http://siteA.com

Los navegadores modernos no bloquearán directamente las solicitudes entre dominios. Si el sitio A solicita una página del sitio B, el navegador realmente buscará la página solicitada en el nivel de la red y verificar si los encabezados de respuesta listan el Sitio A como un dominio de solicitante permitido. Si el Sitio B no ha indicado que el Sitio A tiene permiso para acceder a esta página, el navegador activará el XMLHttpRequestes error evento y denegar los datos de respuesta al código JavaScript solicitante.

Solicitudes no simples

Lo que sucede en el nivel de red puede ser ligeramente más complejo que explicado arriba. Si la solicitud es una solicitud "no simple", el navegador primero envía una solicitud OPCIONES de "verificación previa" sin datos, para verificar que el servidor aceptará la solicitud. Una solicitud no es simple cuando cualquiera (o ambos):

  • usar un verbo HTTP distinto de GET o POST (por ejemplo, PUT, DELETE)
  • usar encabezados de solicitud no simples; los únicos encabezados de solicitudes simples son:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (Esto es solo simple cuando su valor es application/x-www-form-urlencoded, multipart/form-data, o text/plain)

Si el servidor responde a la verificación previa OPTIONS con los encabezados de respuesta apropiados (Access-Control-Allow-Headers para encabezados no simples, Access-Control-Allow-Methodspara verbos no simples) que coincidan con el verbo no simple y / o encabezados no simples, entonces el navegador envía la solicitud real.

Suponiendo que el Sitio A desea enviar una solicitud PUT para /somePage, con un no simple Content-Type valor de application/json, el navegador primero enviaría una solicitud de verificación previa:

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

Tenga en cuenta que Access-Control-Request-Method y Access-Control-Request-Headers son agregadas por el navegador automáticamente; no necesita agregarlos. Preflight de OPCIONES obtiene los encabezados de respuesta exitosos:

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

Al enviar la solicitud real (después de que se haya realizado la verificación previa), el comportamiento es idéntico a cómo se maneja una solicitud simple. En otras palabras, una solicitud no simple cuya verificación previa es exitosa se trata igual que una solicitud simple (es decir, el servidor aún debe enviar Access-Control-Allow-Origin de nuevo para la respuesta real).

Los navegadores envían la solicitud real:

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json

{ "myRequestContent": "JSON is so great" }

Y el servidor devuelve un Access-Control-Allow-Origin, tal como lo haría con una simple solicitud:

Access-Control-Allow-Origin: http://siteA.com

Ver Comprender XMLHttpRequest sobre CORS para obtener un poco más de información sobre solicitudes no simples.


1020
2018-05-17 13:33



Intercambio de solicitudes de origen cruzado - CORS (A.K.A. solicitud AJAX entre dominios) es un problema que la mayoría de los desarrolladores web pueden encontrar, de acuerdo con Same-Origin-Policy, los navegadores restringen el JavaScript del cliente en un entorno limitado de seguridad, por lo general, JS no puede comunicarse directamente con un servidor remoto desde un dominio diferente. En el pasado, los desarrolladores crearon muchas formas complicadas de lograr la solicitud de recursos de dominio cruzado, la mayoría de las veces las formas de uso son:

  1. Use Flash / Silverlight o el lado del servidor como un "proxy" para comunicarse con control remoto
  2. JSON con relleno (JSONP)
  3. Incrusta servidor remoto en un iframe y se comunica a través de fragmento o window.name, consulte aquí.

Esas formas engañosas tienen más o menos algunos problemas, por ejemplo, JSONP puede dar como resultado un agujero de seguridad si los desarrolladores simplemente lo "evalúan", y # 3 arriba, aunque funciona, ambos dominios deben construir un contrato estricto entre ellos, ni flexible ni elegante EN MI HUMILDE OPINIÓN:)

W3C introdujo el Intercambio de recursos de origen cruzado (CORS) como una solución estándar para proporcionar una forma estándar segura, flexible y recomendada para resolver este problema.

El mecanismo

Desde un nivel alto, podemos simplemente considerar que CORS es un contrato entre la llamada AJAX del cliente del dominio A y una página alojada en el dominio B, una solicitud / respuesta típica de origen cruzado sería:

DomainA AJAX solicitud de encabezados

Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com 

Cabeceras de respuesta de DomainB

Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive

Las partes azules que marqué anteriormente fueron los hechos kernal, el encabezado de solicitud "Origen" indica de dónde proviene la solicitud de origen cruzado o la solicitud de verificación previa, el encabezado de respuesta "Control de acceso-permitir-origen" indica que esta página permite la solicitud remota de DomainA (si el valor es * indica permite solicitudes remotas desde cualquier dominio).

Como mencioné anteriormente, W3 recomienda el navegador para implementar un "solicitud previa"antes de enviar la solicitud HTTP de origen cruzado, en pocas palabras, es un HTTP OPTIONS solicitud:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

Si foo.aspx es compatible con el verbo OPTIONS HTTP, puede devolver la respuesta siguiente:

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json

Solo si la respuesta contiene "Access-Control-Allow-Origin" Y su valor es "*" o contiene el dominio que envió la solicitud CORS, al satisfacer esta condición mandista, el navegador enviará la solicitud real Cross-Domain y guardará el resultado en "Preflight-Result-Cache".

Publiqué sobre CORS hace tres años: Solicitud de HTTP de origen cruzado AJAX


102
2018-01-23 13:54



La pregunta es un poco vieja para responder, pero la estoy publicando para futuras referencias a esta pregunta.

De acuerdo a esta Artículo de Mozilla Developer Network,

Un recurso hace una solicitud HTTP de origen cruzado cuando solicita un recurso de un dominio o puerto diferente al que sirve el primer recurso en sí.

enter image description here

Un Página HTML servido desde http://domain-a.com hace una <img> solicitud de src para http://domain-b.com/image.jpg.
Muchas páginas en la web hoy cargan recursos como Hojas de estilo CSS, imágenes y guiones de dominios separados (por lo tanto, debería ser genial).

Política del mismo origen

Por razones de seguridad, los navegadores restringen HTTP de origen cruzado peticiones iniciado desde dentro de scripts.
Por ejemplo, XMLHttpRequest y Fetch siga el política del mismo origen.
Entonces, una aplicación web usando XMLHttpRequest o Fetch solo podía hacer Solicitudes HTTP a su propio dominio.

Intercambio de recursos de origen cruzado (CORS)

Para mejorar las aplicaciones web, los desarrolladores solicitaron a los proveedores de navegadores que permitieran solicitudes entre dominios.

los Intercambio de recursos de origen cruzado (CORS) mecanismo da servidores web controles de acceso entre dominios, que permiten transferencias de datos seguras entre dominios.
El uso moderno de los navegadores CORS en una Contenedor API - como XMLHttpRequest o Fetch - mitigar los riesgos de solicitudes HTTP de origen cruzado.

Cómo funciona CORS (Access-Control-Allow-Origin encabezamiento)

Wikipedia:

El estándar CORS describe nuevos encabezados HTTP que proporcionan a los navegadores y servidores una forma de solicitar URL remotas solo cuando tienen permiso.

Aunque el servidor puede realizar alguna validación y autorización, generalmente es responsabilidad del navegador para apoyar estos encabezados y cumplir con las restricciones que imponen.

Ejemplo

  1. El navegador envía el OPTIONS solicitud con un Origin HTTP encabezamiento.

    El valor de este encabezado es el dominio que sirvió para la página principal. Cuando una página de http://www.example.com intenta acceder a los datos de un usuario en service.example.com, el siguiente encabezado de solicitud se enviaría a service.example.com:

    Origen: http://www.example.com

  2. El servidor en service.example.com puede responder con:

    • Un Access-Control-Allow-Origin Encabezado (ACAO) en su respuesta que indica qué sitios de origen están permitidos.
      Por ejemplo:

      Access-Control-Allow-Origin: http://www.example.com

    • Una página de error si el servidor no permite la solicitud de origen cruzado

    • Un Access-Control-Allow-Origin (ACAO) encabezado con un comodín que permite todos los dominios:

      Access-Control-Allow-Origin: *


33
2018-03-05 06:39



Si solo desea probar una aplicación de dominio cruzado en la que el navegador bloquea su solicitud, entonces puede simplemente abrir su navegador en modo inseguro y probar su aplicación sin cambiar su código y sin hacer que su código sea inseguro. Desde MAC OS puedes hacer esto desde la línea de terminal:

open -a Google\ Chrome --args --disable-web-security --user-data-dir

8
2018-02-22 16:32



1. Un cliente descarga el código de JavaScript MyCode.js de http: // siteA - el origen.

El código que realiza la descarga, la etiqueta de script html o xhr de javascript o lo que sea, proviene de, digamos, http: // siteZ. Y, cuando el navegador solicita MyCode.js, envía un origen: encabezado que dice "Origen: http: // siteZ", porque puede ver que está solicitando siteA y siteZ! = siteA. (No puede detener o interferir con esto).

2. El encabezado de respuesta de MyCode.js contiene Access-Control-Allow-Origin: http: // siteB, lo que pensé que significaba que a MyCode.js se le permitía hacer referencias de origen cruzado al sitio B.

no. Significa que solo el sitio B puede hacer esta solicitud. Por lo tanto, su solicitud de MyCode.js desde siteZ recibe un error, y el navegador normalmente no le da nada. Pero si haces que tu servidor devuelva A-C-A-O: siteZ, obtendrás MyCode.js. O si envía '*', eso funcionará, eso dejará entrar a todos. O si el servidor siempre envía la cadena desde el encabezado Origen: ... pero ... por seguridad, si le teme a los piratas informáticos , su servidor solo debe permitir orígenes en una lista restringida, que pueden hacer esas solicitudes.

Entonces, MyCode.js viene de siteA. Cuando realiza solicitudes al sitioB, todas son de origen cruzado, el navegador envía Origen: sitioA, y el sitioB tiene que tomar el sitioA, reconocer que está en la lista breve de solicitantes permitidos y devolver A-C-A-O: sitioA. Solo entonces el navegador permitirá que su script obtenga el resultado de esas solicitudes.


6
2018-02-27 01:37



trabajo con express 4 y nodo 7.4 y angular, tuve el mismo problema que ayudo esto:
  a) lado del servidor: en el archivo app.js doy encabezados a todas las respuestas como:

app.use(function(req, res, next) {  
      res.header('Access-Control-Allow-Origin', req.headers.origin);
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
 });  

esto debe tener antes de todo enrutador.
Vi muchos añadidos estos encabezados:

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

pero no necesito eso,
b) lado del cliente: en enviar ajax debe agregar: "conCredentials: true", como:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });

buena suerte.


5
2018-02-06 08:19



Utilizando Reaccionar y Axios, une el enlace proxy a la URL y agrega el encabezado como se muestra a continuación

https://cors-anywhere.herokuapp.com/ + Your API URL

Solo agregando el enlace Proxy funcionará, pero también puede generar un error para No Access nuevamente. Por lo tanto, es mejor agregar un encabezado como se muestra a continuación.

axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
      .then(response => console.log(response:data);
  }

5
2017-10-16 15:53