javascript - habilitar - ¿Cómo funciona el encabezado de Access-Control-Allow-Origin?
cors javascript (11)
Cuando empiezo a pensar en CORS, mi intuición acerca de qué sitio aloja los encabezados es incorrecta, tal como lo describió en su pregunta. Para mí, es útil pensar en el propósito de la misma política de origen.
El propósito de la misma política de origen es protegerlo de JavaScript malicioso en siteA.com que accede a la información privada que ha elegido compartir solo con siteB.com. Sin la misma política de origen, JavaScript escrito por los autores de siteA.com podría hacer que su navegador realice solicitudes a siteB.com, utilizando sus cookies de autenticación para siteB.com. De esta manera, siteA.com podría robar la información secreta que usted comparte con siteA.com.
A veces es necesario trabajar en varios dominios, que es donde entra CORS. CORS relaja la misma política de origen para domainA.com, utilizando el encabezado Access-Control-Allow-Origin
para enumerar otros dominios (domainB.com) en los que se confía para ejecutar JavaScript que puede interactuar con domainA.com.
Para entender qué dominio debe servir a los encabezados de CORS, considere esto. Visita malware.com, que contiene algunos JavaScript que intentan realizar una solicitud de dominio cruzado a mybank.com. Debería estar en mybank.com, no malicioso.com, para decidir si establece o no encabezados CORS que relajen la misma política de origen permitiendo que el JavaScript de malicioso.com interactúe con él. Si fuera posible para malicous.com establecer sus propios encabezados CORS permitiendo su propio acceso de JavaScript a mybank.com, esto anularía completamente la misma política de origen.
Creo que la razón de mi mala intuición es el punto de vista que tengo al desarrollar un sitio. Es mi sitio, con todo mi JavaScript, por lo tanto, no hace nada malicioso y debería depender de mí especificar con qué otros sitios puede interactuar mi JavaScript. Cuando, de hecho, debería pensar qué otros sitios JavaScript están intentando interactuar con mi sitio y ¿debo usar CORS para permitirlos?
Al parecer, he malinterpretado completamente su semántica. Pensé en algo como esto:
- Un cliente descarga código javascript MyCode.js de http: // siteA - el origen .
- El encabezado de respuesta de MyCode.js contiene Access-Control-Allow-Origin: http: // siteB , lo que pensé significaba que MyCode.js tenía permitido hacer referencias de origen cruzado al sitio B.
- 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. Por lo tanto, he leído Intercambio de recursos de origen cruzado e intento 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 control total del sitio A y 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.
En Python he estado usando la biblioteca Flask-CORS
con gran éxito. Hace que tratar con CORS sea muy fácil e indoloro. Agregué algún código de la documentación de la biblioteca a continuación.
Instalación:
$ pip install -U flask-cors
Ejemplo simple que permite CORS para todos los dominios en todas las rutas:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"
Para ejemplos más específicos vea la documentación. He utilizado el sencillo ejemplo anterior para solucionar el problema de CORS en una aplicación iónica que estoy creando y que tiene que acceder a un servidor matraz separado.
Intercambio de solicitudes de origen cruzado: CORS
(también conocido como solicitud AJAX de dominio cruzado) es un problema que la mayoría de los desarrolladores web pueden encontrar, según la Política del mismo origen, los navegadores restringen el JavaScript del cliente en un recinto de seguridad, por lo general, JS no puede comunicarse directamente con un remoto servidor de un dominio diferente. En el pasado, los desarrolladores crearon muchas formas difíciles de lograr la solicitud de recursos entre dominios, las formas más comunes de uso son:
- Use Flash / Silverlight o el lado del servidor como un "proxy" para comunicarse con el control remoto.
- JSON con relleno ( JSONP ).
- Inserta el servidor remoto en un iframe y comunícate a través de fragment o window.name, consulta here .
Esas formas complicadas tienen más o menos algunos problemas, por ejemplo, JSONP puede resultar en un agujero de seguridad si los desarrolladores simplemente lo "evalúan", y # 3 arriba, aunque funciona, ambos dominios deben establecer un contrato estricto entre ellos, ni flexible ni elegante EN MI HUMILDE OPINIÓN:)
El W3C introdujo el Intercambio de recursos de origen cruzado (CORS, por sus siglas en inglés) 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, simplemente podemos considerar que CORS es un contrato entre la llamada AJAX del cliente desde el dominio A y una página alojada en el dominio B, una solicitud / respuesta típica de origen cruzado sería:
Encabezados de solicitud AJAX de DomainA
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
Encabezados 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é arriba fueron los datos del kernal, el encabezado de solicitud "Origen" indica donde la solicitud de origen cruzado o solicitud de verificación previa se origina en ", el encabezado de respuesta" Control-Permitir-Origen "indica que esta página permite la solicitud remota desde DomainA (si el valor es * indica permite solicitudes remotas desde cualquier dominio).
Como mencioné anteriormente, W3 recomendó que el navegador implemente una " solicitud de verificación previa " antes de enviar la solicitud HTTP de origen cruzado, en pocas palabras, es una solicitud de OPTIONS
HTTP:
OPTIONS DomainB.com/foo.aspx HTTP/1.1
Si foo.aspx admite el verbo HTTP OPCIONES, podría devolver una respuesta como la 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 cumplir con esta condición obligatoria, el navegador enviará la solicitud real entre dominios y almacenará en caché el resultado. en " Preflight-Result-Cache ".
Hice un blog sobre CORS hace tres años: AJAX Solicitud HTTP de origen cruzado
La pregunta es demasiado antigua para responder, pero estoy publicando esto para cualquier referencia futura a esta pregunta.
Según this artículo de la Red de Desarrolladores de Mozilla,
Un recurso realiza una solicitud HTTP de origen cruzado cuando solicita un recurso de un dominio o puerto diferente al que sirve el primer recurso.
Una página HTML servida desde http://domain-a.com
realiza una solicitud de <img>
src para http://domain-b.com/image.jpg
.
Muchas páginas en la web actual cargan recursos como hojas de estilo CSS , imágenes y scripts de dominios separados (por lo tanto, debería ser genial).
Política del mismo origen
Por razones de seguridad, los navegadores restringen las solicitudes HTTP de origen cruzado iniciadas desde los scripts .
Por ejemplo, XMLHttpRequest
y Fetch
siguen la política del mismo origen .
Por lo tanto, una aplicación web que utiliza XMLHttpRequest
o Fetch
solo puede realizar solicitudes HTTP a su propio dominio .
Intercambio de recursos de origen cruzado (CORS)
Para mejorar las aplicaciones web, los desarrolladores pidieron a los proveedores de navegadores que permitieran las solicitudes de varios dominios.
El mecanismo de Intercambio de recursos de origen cruzado (CORS, por sus siglas en inglés) proporciona a los servidores web controles de acceso de dominio cruzado , que permiten la transferencia segura de datos entre dominios.
Los navegadores modernos utilizan CORS en un contenedor de API , como XMLHttpRequest
o Fetch
, para mitigar los riesgos de solicitudes HTTP de origen cruzado.
Cómo funciona CORS (encabezado Access-Control-Allow-Origin
)
El estándar CORS describe los nuevos encabezados HTTP que proporcionan a los navegadores y servidores una forma de solicitar direcciones URL remotas solo cuando tienen permiso.
Aunque el servidor puede realizar alguna validación y autorización, generalmente es responsabilidad del navegador dar soporte a estos encabezados y respetar las restricciones que imponen.
Ejemplo
El navegador envía la solicitud de
OPTIONS
con un encabezadoOrigin HTTP
.El valor de este encabezado es el dominio que sirve a la página principal. Cuando una página de
http://www.example.com
intenta acceder a los datos de un usuario enservice.example.com
, el siguiente encabezado de solicitud se enviará aservice.example.com
:Origen: http://www.example.com
El servidor en
service.example.com
puede responder con:Un encabezado
Access-Control-Allow-Origin
(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 encabezado
Access-Control-Allow-Origin
(ACAO) con un comodín que permite todos los dominios:Access-Control-Allow-Origin: *
Para compartir el origen cruzado, establezca el encabezado: ''Access-Control-Allow-Origin'':''*'';
Php: header(''Access-Control-Allow-Origin'':''*'');
Nodo: app.use(''Access-Control-Allow-Origin'':''*'');
Esto permitirá compartir contenido para diferentes dominios.
Si está utilizando PHP, intente agregar el siguiente código al doblar el archivo php:
Si está usando localhost, intente esto:
header("Access-Control-Allow-Origin: *");
Si está usando dominios externos como el servidor, intente esto:
header("Access-Control-Allow-Origin: http://www.website.com");
Si solo desea probar una aplicación de dominio cruzado en la que el navegador bloquea su solicitud, puede abrir su navegador en modo no seguro 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
Utilizando React y Axios , une el enlace del 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 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);
}
Yo trabajo con Express 4 y node 7.4 y angular, tuve el mismo problema, me ayudó 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 todos los enrutadores .
Vi muchos agregados a 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) del lado del cliente: en el envío ajax necesita agregar: "withCredentials: true", como:
$http({
method: ''POST'',
url: ''url,
withCredentials: true,
data : {}
}).then(function(response){
// code
}, function (response) {
// code
});
buena suerte.
Access-Control-Allow-Origin
es un encabezado CORS (Intercambio de recursos de origen cruzado) .
Cuando el Sitio A trata de obtener contenido del Sitio B, el Sitio B puede enviar un encabezado de respuesta de Access-Control-Allow-Origin
para indicar al navegador que el contenido de esta página es accesible a ciertos orígenes. (Un origen es un dominio, más un esquema y un número de puerto ). De forma predeterminada, las páginas del Sitio B no son accesibles a ningún otro origen ; El uso del encabezado Access-Control-Allow-Origin
abre una puerta para el acceso de origen cruzado por orígenes de solicitud específicos.
Para cada recurso / página que el sitio B quiere hacer accesible al sitio A, el sitio B debe servir sus páginas con el encabezado de respuesta:
Access-Control-Allow-Origin: http://siteA.com
Los navegadores modernos no bloquearán las solicitudes de dominios cruzados. 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 incluyen 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 evento de error
XMLHttpRequest
y negará los datos de respuesta al código JavaScript que solicita.
Peticiones no simples
Lo que sucede en el nivel de la red puede ser un poco más complejo de lo que se explicó anteriormente. Si la solicitud es una solicitud "no simple" , el navegador envía primero una solicitud OPCIONES de "verificación previa" sin datos, para verificar que el servidor acepte la solicitud. Una solicitud no es simple cuando (o ambas):
- utilizando un verbo HTTP que no sea GET o POST (por ejemplo, PUT, DELETE)
- utilizando encabezados de solicitud no simples; Los únicos encabezados de peticiones simples son:
-
Accept
-
Accept-Language
-
Content-Language
-
Content-Type
(esto es simple cuando su valor esapplication/x-www-form-urlencoded
,multipart/form-data
otext/plain
)
-
Si el servidor responde a la verificación previa de OPCIONES con encabezados de respuesta apropiados ( Access-Control-Allow-Headers
para Access-Control-Allow-Headers
no simples, Access-Control-Allow-Methods
para verbos no simples) que coinciden con el verbo no simple y / o non -simple encabezados, entonces el navegador envía la solicitud real.
Suponiendo que el Sitio A desea enviar una solicitud PUT para /somePage
, con un valor de Content-Type
no simple de application/json
, el navegador enviaría primero 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 el navegador agrega automáticamente el Access-Control-Request-Method
Access-Control-Request-Headers
; No es necesario agregarlos. Esta verificación previa 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 realizar 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 de la misma manera que una solicitud simple (es decir, el servidor todavía debe enviar Access-Control-Allow-Origin
nuevamente 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 envía un Access-Control-Allow-Origin
, como lo haría para una simple solicitud:
Access-Control-Allow-Origin: http://siteA.com
Consulte Comprender XMLHttpRequest sobre CORS para obtener más información sobre solicitudes no simples.
1. Un cliente descarga el código javascript MyCode.js de http: // siteA - el origen.
El código que realiza la descarga (su etiqueta de secuencia de comandos html o xhr de javascript o lo que sea) proviene de, digamos, http: // siteZ . Y, cuando el navegador solicita MyCode.js, envía un encabezado Origin: "Origin: http: // siteZ ", porque puede ver que estás solicitando a siteA y siteZ! = SiteA. (No puedes parar o interferir con esto.)
2. El encabezado de respuesta de MyCode.js contiene Access-Control-Allow-Origin: http: // siteB , lo que pensé significaba que MyCode.js tenía permitido hacer referencias de origen cruzado al sitio B.
no. Significa que solo se permite que siteB realice 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 ACAO: siteZ, obtendrás MyCode.js. O si envía ''*'', eso funcionará, dejará entrar a todos. O si el servidor siempre envía la cadena desde el encabezado Origin: pero ... por seguridad, si tienes miedo de los hackers , su servidor solo debe permitir orígenes en una lista restringida, que tengan permiso para realizar esas solicitudes.
Entonces, MyCode.js viene de siteA. Cuando realiza solicitudes a siteB, todas son de origen cruzado, el navegador envía Origin: siteA, y siteB tiene que tomar el sitioA, reconocer que está en la lista corta de solicitantes permitidos y enviar ACAO: siteA. Solo entonces el navegador permitirá que su script obtenga el resultado de esas solicitudes.