¿Por qué mi código JavaScript recibe el error "No hay encabezado 'Access-Control-Allow-Origin' presente en el recurso solicitado", mientras que Postman no lo recibe?
Frecuentes
Visto 5,839 veces
3168
Nota mod: Esta pregunta es sobre por qué
XMLHttpRequest
/fetch
/etc. en el navegador están sujetos a las mismas restricciones de política de acceso (obtiene errores que mencionan CORB o CORS), mientras que Postman no lo está. esta pregunta es no sobre cómo solucionar el error "No 'Access-Control-Allow-Origin'...". Se trata de por qué suceden.
Por favor deja de publicar:
- Configuraciones de CORS para todos los lenguajes/marcos bajo el sol. En cambio encuentre la pregunta de su idioma/marco relevante.
- Servicios de terceros que permiten una solicitud para eludir CORS
- Opciones de línea de comandos para desactivar CORS para varios navegadores
Estoy tratando de hacer la autorización usando JavaScript al conectarse a la Sosegado API incorporado Frasco. Sin embargo, cuando hago la solicitud, me sale el siguiente error:
XMLHttpRequest cannot load http://myApiUrl/login.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'null' is therefore not allowed access.
Sé que la API o el recurso remoto deben establecer el encabezado, pero ¿por qué funcionó cuando hice la solicitud a través de la extensión de Chrome? Cartero?
Este es el código de la solicitud:
$.ajax({
type: 'POST',
dataType: 'text',
url: api,
username: 'user',
password: 'pass',
crossDomain: true,
xhrFields: {
withCredentials: true,
},
})
.done(function (data) {
console.log('done');
})
.fail(function (xhr, textStatus, errorThrown) {
alert(xhr.responseText);
alert(textStatus);
});
13 Respuestas
1622
Si entendí bien, estás haciendo un XMLHttpRequest a un dominio diferente al que se encuentra su página. Por lo que el navegador lo está bloqueando ya que suele permitir una petición en el mismo origen por motivos de seguridad. Debe hacer algo diferente cuando desee realizar una solicitud entre dominios.
Cuando utiliza Postman, no están restringidos por esta política. Citado de XMLHttpRequest de origen cruzado:
Las páginas web normales pueden usar el objeto XMLHttpRequest para enviar y recibir datos de servidores remotos, pero están limitadas por la misma política de origen. Las extensiones no son tan limitadas. Una extensión puede hablar con servidores remotos fuera de su origen, siempre que primero solicite permisos de origen cruzado.
Respondido el 12 de Septiembre de 22 a las 03:09
El navegador no está bloqueando la solicitud. Los únicos navegadores que bloquean directamente las solicitudes ajax de origen cruzado son IE7 o anteriores. Todos los navegadores, excepto IE7 y anteriores, implementan la especificación CORS (IE8 e IE9 parcialmente). Todo lo que necesita hacer es optar por las solicitudes CORS en su servidor API devolviendo los encabezados adecuados según la solicitud. Debe leer sobre los conceptos de CORS en mzl.la/VOFrSz. Postman también envía solicitudes a través de XHR. Si no ve el mismo problema cuando usa el cartero, esto significa que, sin saberlo, no está enviando la misma solicitud a través del cartero. - ray nicholus
@ MD.SahibBinMahboob Postman NO está enviando una solicitud "desde su código java/python". Está enviando la solicitud directamente desde el navegador. XHR en las extensiones de Chrome funciona un poco diferente, especialmente cuando se trata de solicitudes de origen cruzado. - ray nicholus
349
ADVERTENCIA: Usar
Access-Control-Allow-Origin: *
puede hacer que su API/sitio web sea vulnerable a solicitud de falsificación a través del sitio (CSRF) ataques. Asegúrate de que entender los riesgos antes de usar este código.
Es muy simple de resolver si estás usando PHP. Simplemente agregue el siguiente script al comienzo de su página PHP que maneja la solicitud:
<?php header('Access-Control-Allow-Origin: *'); ?>
Si está utilizando Nodo-rojo tienes que permitir CORS en el capítulo respecto a la node-red/settings.js
archivo descomentando las siguientes líneas:
// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
origin: "*",
methods: "GET,PUT,POST,DELETE"
},
Si está utilizando Frasco igual que la pregunta; primero tienes que instalar flask-cors
pip install -U flask-cors
Luego incluye el frasco cuernos paquete en su aplicación.
from flask_cors import CORS
Una aplicación simple se verá así:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"
Para más detalles, puede consultar el Documentación del matraz.
Respondido el 04 de Septiembre de 22 a las 22:09
No deberias apagar CORS porque no sabes para que sirve. Esto deja a sus usuarios en un estado fundamentalmente inseguro. - user229044
Aunque podría no ser seguro, la pregunta no era sobre la seguridad, sino sobre cómo realizar la tarea. Esta es una de las opciones que un desarrollador tiene para elegir cuando se trata de solicitudes AJAX entre dominios. Me ayudó a resolver el problema y, para mi aplicación, no me importa de dónde provienen los datos. Desinfecto toda la entrada con PHP en el dominio de destino, por lo que, si alguien quiere publicar algo basura, que lo intente. El punto principal aquí es que se puede permitir AJAX entre dominios desde el dominio de destino. +1 por la respuesta. - ZurabWeb
@meagar Estoy de acuerdo con usted en que no debemos apagar CORS, pero a veces necesitamos probar la aplicación mientras la desarrollamos y, para eso, la forma más fácil es apagar CORS y verificar si todo funciona bien. Muchas veces, los desarrolladores frontend no tienen acceso al sistema backend donde pueden cambiar las cosas o necesitan escribir un proxy para lo mismo. La mejor manera de agregar una extensión de Chrome que desactive CORS con fines de desarrollo, como está escrito en la respuesta que se elimina. - shruti
Debería ser muy útil si la respuesta (o la edición con la ADVERTENCIA en la parte superior) explicara quién es arriesgado si usa ese script de encabezado () en php. La pregunta aquí es sobre un sitio extraño donde no tenemos control, y que solo nos permite navegar y verlo desde un navegador, mientras que si necesitamos acceder a los recursos de nuestro servidor en su lugar, inicia la protección CORS (para no dejarnos realizar demasiadas consultas por segundo). Por lo tanto, mi pregunta sigue en pie, ¿qué peligros tenemos los visitantes si usamos en NUESTRO servidor ese script de encabezado ()? ¿El editor confundió al visitante (nosotros) con el anfitrión? - Eva
¡La protección de @Eve CORS no se trata de la cantidad de consultas por segundo! Rechaza cualquier otro sitio web para utilizar su servicio o página de recursos. La advertencia ya contiene dos enlaces para explicar cuáles son los riesgos: Shady Mohamed Sherif
102
Gracias
$.ajax({tipo: "POST" - llamadas OPCIONES
$ .post ( - llamadas PUBLICAR
Ambos son diferentes. Cartero llama "POST" correctamente, pero cuando lo llamemos, será "OPCIONES".
Para servicios web C#: API web
Por favor agregue el siguiente código en su web.config archivo bajo el etiqueta. Esto funcionará:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
Asegúrese de no estar cometiendo ningún error en la llamada de Ajax.
jQuery
$.ajax({
url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
type: "POST", /* or type:"GET" or type:"PUT" */
dataType: "json",
data: {
},
success: function (result) {
console.log(result);
},
error: function () {
console.log("error");
}
});
Nota: Si buscas descargar contenido de un sitio web de terceros luego esto no te ayudara. Puede probar el siguiente código, pero no JavaScript.
System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
Respondido el 04 de Septiembre de 22 a las 22:09
70
Profundo
En la siguiente investigación como API, uso http://example.com en lugar de http://myApiUrl/login de su pregunta, porque este primero funciona. Supongo que su página está en http://my-site.local:8088.
NOTA: ¡La API y tu página tienen dominios diferentes!
La razón por la que ve resultados diferentes es que Postman:
- establecer encabezado
Host=example.com
(su API) - NO establecer encabezado
Origin
- El cartero en realidad no usa la URL de su sitio web en absoluto (solo ingresa su dirección API en el cartero); solo envía una solicitud a la API, por lo que asume que el sitio web tiene la misma dirección que la API (el navegador no asume esto)
Esto es similar a la forma en que los navegadores envían solicitudes cuando el sitio y la API tienen el mismo dominio (los navegadores también configuran el elemento de encabezado Referer=http://my-site.local:8088
, sin embargo no lo veo en Postman). Cuándo Origin
el encabezado es no establecido, por lo general los servidores permiten este tipo de solicitudes de forma predeterminada.
Esta es la forma estándar en que Postman envía solicitudes. Pero un navegador envía solicitudes de manera diferente cuando su sitio y API tienen diferentes dominios, y entonces CORS ocurre y el navegador automáticamente:
- establece el encabezado
Host=example.com
(tuyo como API) - establece el encabezado
Origin=http://my-site.local:8088
(Tú sitio)
(El encabezado Referer
tiene el mismo valor que Origin
). Y ahora en Chrome Consola y Redes pestaña verás:
Cuando tengas Host != Origin
esto es CORS, y cuando el servidor detecta tal solicitud, generalmente lo bloquea por defecto.
Origin=null
se establece cuando abre contenido HTML desde un directorio local y envía una solicitud. La misma situación es cuando envías una solicitud dentro de un <iframe>
, como en el fragmento a continuación (pero aquí el Host
el encabezado no está configurado en absoluto) - en general, en todas partes donde la especificación HTML dice origen opaco, puede traducir eso a Origin=null
. Más información sobre esto se puede encontrar aquí.
fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab
Si no utiliza una solicitud CORS simple, por lo general, el navegador también envía automáticamente una solicitud de OPCIONES antes de enviar la solicitud principal; se proporciona más información. aquí. El siguiente fragmento lo muestra:
fetch('http://example.com/api', {
method: 'POST',
headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)
Puede cambiar la configuración de su servidor para permitir solicitudes CORS.
Aquí hay una configuración de ejemplo que enciende CORS en nginx (archivo nginx.conf) - tenga mucho cuidado con la configuración always/"$http_origin"
para nginx y "*"
para Apache: esto desbloqueará CORS de cualquier dominio (en producción, en lugar de estrellas, use la dirección de su página concreta que consume su API)
location ~ ^/index\.php(/|$) {
...
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
}
Aquí hay una configuración de ejemplo que enciende CORS en Apache (archivo .htaccess)
# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests |
# ------------------------------------------------------------------------------
# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/
# <IfModule mod_headers.c>
# Header set Access-Control-Allow-Origin "*"
# </IfModule>
# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"
Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"
Respondido 19 Feb 22, 19:02
¡Excelente, excelente explicado y fácil de ponerse al día! ¡Gracias! - Nam G VU
Esta respuesta demuestra claramente lo que este comentario describe: If you are not seeing the same problem when using postman, this means that you are unknowingly not sending the same request via postman
. ¡Bien hecho! - ray jason
38
La aplicación de una restricción CORS es una característica de seguridad definida por un servidor e implementada por un cada navegador.
El navegador mira la política CORS del servidor y la respeta.
Sin embargo, la herramienta Postman no se preocupa por la política CORS del servidor.
Por eso aparece el error CORS en el navegador, pero no en Postman.
respondido 08 mar '20, 18:03
33
El error que obtiene se debe al estándar CORS, que establece algunas restricciones sobre cómo JavaScript puede realizar solicitudes ajax.
El estándar CORS es un estándar del lado del cliente, implementado en el navegador. Por lo tanto, es el navegador el que evita que se complete la llamada y genera el mensaje de error, no el servidor.
Postman no implementa las restricciones de CORS, por lo que no ve el mismo error al realizar la misma llamada desde Postman.
¿Por qué ¿Postman no implementa CORS? CORS define las restricciones relativas al origen (dominio URL) de la página que inicia la solicitud. Pero en Postman, las solicitudes no se originan en una página con una URL, por lo que CORS no se aplica.
Respondido 06 Abr '21, 11:04
@MrJedi: la respuesta aceptada no explica por qué la solicitud tiene éxito en Postman, que era la pregunta original. - JacquesB
Los servidores originalmente estaban destinados a enviar flujos a clientes (programas de software de navegador), no a varias aplicaciones de escritorio o servidor, sino que podrían comportarse de manera retorcida. Un navegador establece un protocolo de negociación con el servidor, recibe la confirmación con respecto a la conexión y luego se reanuda el flujo de datos. Hubo situaciones (DDOS) en las que los servidores de granjas de bots enviaron millones de consultas y el host comprometió muchos recursos (procesos abiertos) para cada una de estas conexiones bloqueadas que finalmente nunca ocurrieron, lo que bloqueó su capacidad para responder a otras solicitudes legítimas. Eva
@Eve: CORS es un lado del cliente medida implementada en el navegador y, por lo tanto, no es algo que pueda evitar los ataques DDOS de las granjas de bots. - JacquesB
esta es en realidad la mejor explicación, y un 'momento ajá' para darse cuenta de que CORS es un navegador estándar. - Aris
14
Orígenes de soluciones y problemas
Estas haciendo un XMLHttpRequest a diferentes dominios, ejemplo:
- Dominio uno:
some-domain.com
- Dominio dos:
some-different-domain.com
Esta diferencia en los nombres de dominio desencadena CORS (Uso compartido de recursos entre orígenes) política llamada SOP (Política del mismo origen) que impone el uso de los mismos dominios (por lo tanto Natural) en Ajax, XMLHttpRequest y otras solicitudes HTTP.
¿Por qué funcionó cuando hice la solicitud a través de la extensión Postman de Chrome?
Un cliente (la mayoría Navegadores y Herramientas de desarrollo) tiene la opción de hacer cumplir la Política del mismo origen.
La mayoría de los navegadores aplican la política de Política del mismo origen para evitar problemas relacionados con CSRF (Falsificación de solicitudes entre sitios) ataque.
Cartero como herramienta de desarrollo elige no aplicar SOP mientras que algunos navegadores lo hacen, es por eso que puede enviar solicitudes a través de Postman que no puede enviar con XMLHttpRequest a través de JS usando el navegador.
Respondido el 03 de enero de 22 a las 11:01
5
Para fines de prueba del navegador:
Windows - Ejecutar:
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
El comando anterior deshabilitará la seguridad web de Chrome. Entonces, por ejemplo, si trabaja en un proyecto local y encuentra un problema de política CORS cuando intenta realizar una solicitud, puede omitir este tipo de error con el comando anterior. Básicamente, abrirá una nueva sesión de Chrome.
Respondido el 05 de Septiembre de 22 a las 09:09
¿Podrías explicarlo? - ZebraCoder
@ZebraCoder El comando anterior deshabilitará la seguridad web de Chrome. Entonces, por ejemplo, si trabaja en un proyecto local y encuentra un problema de política de CORS al intentar realizar una solicitud, puede omitir este tipo de error con el comando anterior. Básicamente, abrirá una nueva sesión de Chrome. - daniel iftimie
¿Puede usted add la información a la respuesta en sí? Los comentarios se pueden eliminar en cualquier momento. (Pero *********************************** sin ******************************* "Editar:", "Actualizar:" o similar: la respuesta debe aparecer como si fue escrito hoy) - Pedro Mortensen
4
También puede recibir este error si el tiempo de espera de su puerta de enlace es demasiado corto y el recurso al que está accediendo tarda más en procesarse que el tiempo de espera. Este puede ser el caso de consultas de bases de datos complejas, etc. Por lo tanto, el código de error anterior puede estar ocultando este problema. Simplemente verifique si el código de error es 504 en lugar de 404 como en la respuesta de kamil o algo mas. Si es 504, entonces aumentar el tiempo de espera de la puerta de enlace podría solucionar el problema.
En mi caso, el error CORS podría eliminarse al deshabilitar la misma política de origen (CORS) en el explorador de Internet navegador, ver Cómo deshabilitar la política del mismo origen Internet Explorer. Después de hacer esto, fue un error 504 puro en el registro.
Respondido el 04 de Septiembre de 22 a las 22:09
Si obtiene el tiempo de espera, no obtiene el error CORS: Señor Jedi
Bueno, tuve problemas para solucionar un sistema y el error de CORS me desconcertó, que era solo el tiempo de espera que era demasiado corto, lo que resultó en una conexión cerrada. Después de aumentar el tiempo de espera, el sistema funcionó perfectamente. Así que sí, el tiempo de espera provocó un error No 'Access-Control-Allow-Origin' que me llevó a este hilo en primer lugar. Así que esto podría ser útil para que otros lo arrojen junto con un 504. - NDM
Más bien significa que algo está mal en la configuración de su aplicación. No debería recibir este error en el tiempo de espera - Señor Jedi
También recibí un confuso error CORS 504 cuando nginx, en mi caso, agotó el tiempo de espera. Al aumentar el tiempo de espera, el servicio volvió a estar en línea sin errores de CORS. Gracias por la pista. - efrú
3
Para resolver este problema, escriba esta línea de código en su doGet()
or doPost()
función cualquiera que esté usando en backend
response.setHeader("Access-Control-Allow-Origin", "*");
En lugar de "*"
puede escribir el sitio web o el punto final de la URL de la API que está accediendo al sitio web; de lo contrario, será público.
respondido 11 nov., 22:06
0
Su dirección IP no está en la lista blanca, por lo que está recibiendo este error. Pídale al personal de back-end que incluya en la lista blanca su dirección IP para el servicio al que está accediendo.
Respondido el 04 de Septiembre de 22 a las 21:09
0
Para mí, tuve este problema por diferentes razones, el dominio remoto se agregó a los orígenes, la aplicación implementada funciona perfectamente, excepto en un punto final, tuve este problema:
Origin https://mai-frontend.vercel.app is not allowed by Access-Control-Allow-Origin. Status code: 500
y
Fetch API cannot load https://sciigo.herokuapp.com/recommendations/recommendationsByUser/8f1bb29e-8ce6-4df2-b138-ffe53650dbab due to access control checks.
Descubrí que la tabla de mi base de datos de Heroku no contiene todas las columnas de mi tabla local después de actualizar la tabla de la base de datos de Heroku, todo funcionó bien.
respondido 28 nov., 22:00
-4
Me funciona aplicando este middleware globalmente:
<?php
namespace App\Http\Middleware;
use Closure;
class Cors {
public function handle($request, Closure $next) {
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', "Accept,authorization,Authorization, Content-Type");
}
}
Respondido el 04 de Septiembre de 22 a las 22:09
Que quieres decir con "aplicando este middleware en todo el mundo"? Puedes elaborar? - Pedro Mortensen
¿Cómo responde esto a la pregunta? La pregunta está etiquetada con JavaScript, jQuery y CORS. Si lo hace, debería ser explicado. La clase tiene el nombre "Cors", pero ¿cómo se relaciona eso? ¿Cuál es la esencia? - Pedro Mortensen
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas javascript jquery cors postman same-origin-policy or haz tu propia pregunta.
¿Estás haciendo la solicitud desde localhost o ejecutando HTML directamente? - MD. Sahib Bin Mahboob
@ MD.SahibBinMahboob Si entiendo su pregunta, la solicito de localhost: tengo una página en mi computadora y simplemente la ejecuto. Cuando implemento el sitio en el alojamiento, se obtiene el mismo resultado. - Mr Jedi
Para cualquiera que busque más lectura, MDN tiene un buen artículo sobre ajax y solicitudes de origen cruzado: developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS - Sam Eaton
Una respuesta a esta pregunta (ahora eliminada y solo visible para 10K'ers) es el tema de metapregunta ¿Por qué esta respuesta votada se eliminó una vez y se eliminó nuevamente cuando se volvió a publicar? - Peter Mortensen
Una inmersión profunda relacionada con CORS en este mismo error, pero que tiene que ver con el caché y los encabezados de S3 / Cloudfront, también se encuentra aquí: stackoverflow.com/questions/44800431/… - OG Sean