¿Por qué el cartero no recibe un error de "No hay un encabezado de "Control de Acceso-Autorización-Origen" en el recurso solicitado" cuando mi código JavaScript lo hace...

javascript jquery cors same-origin-policy flask-restless


Nota de modificación : esta pregunta es acerca de por qué Postman no está sujeto a restricciones CORS de la misma manera que lo está XMLHttpRequest. Esta pregunta no se trata de cómo solucionar un error "No 'Access-Control-Allow-Origin' ...".

Por favor, deja de publicar :

  • Configuraciones CORS para cada idioma / marco bajo el sol. En su lugar, encuentre la pregunta relevante de su lenguaje / marco .
  • Servicios de terceros que permiten una solicitud para eludir el CORS
  • Opciones de línea de comando para apagar el CORS para varios navegadores

Estoy tratando de hacer una autorización usando JavaScript conectándome al Frasco incorporado RESTful API . Sin embargo, cuando hago la solicitud, aparece el siguiente error:

XMLHttpRequest no puede cargar http: // myApiUrl / login . No hay encabezado 'Access-Control-Allow-Origin' presente en el recurso solicitado. Por lo tanto, el origen 'nulo' no tiene acceso permitido.

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 Postman ?

Este es el código de 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);
    });




Answer 1 MD. Sahib Bin Mahboob


Si lo entendí bien, estás haciendo una solicitud XMLHttpRequest a un dominio diferente al de tu página. Por lo tanto, el navegador lo bloquea, ya que generalmente permite una solicitud en el mismo origen por razones de seguridad. Debe hacer algo diferente cuando desee hacer una solicitud de dominio cruzado. Un tutorial sobre cómo lograr eso es usar CORS .

Cuando utiliza cartero, no están restringidos por esta política. Citado de Cross-Origin XMLHttpRequest :

Las páginas web normales pueden utilizar 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 están tan limitadas.Una extensión puede hablar con servidores remotos fuera de su origen,siempre y cuando primero solicite permisos de origen cruzado.




Answer 2 Shady Sherif


ADVERTENCIA: El uso de Access-Control-Allow-Origin: * puede hacer que su API / sitio web sea vulnerable a ataques de falsificación de solicitudes entre sitios (CSRF). Asegúrese de comprender los riesgos antes de usar este código.

Es muy simple de resolver si está 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 Node-red , debe permitir CORS en el archivo node-red/settings.js 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 Flask igual que la pregunta; primero tiene que instalar flask-cors

$ pip install -U flask-cors

Entonces incluye el corsario de Flask en tu solicitud.

from flask_cors import CORS

Una simple aplicación se verá como:

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 la documentación del Frasco .




Answer 3 George Livingston


Because
$ .ajax ({type: "POST" - llama a OPTIONS
$ .post ( - Llamadas POST

Ambos son diferentes.El cartero llama "POST" correctamente,pero cuando lo llamemos,será "OPCIONES".

Para servicios web C #: API web

Agregue el siguiente código en su archivo web.config bajo la etiqueta <system.webServer>. Esto funcionará:

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
</httpProtocol>

Por favor,asegúrate de no cometer 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");
    }
});

Problema de Angular 4: consulte http://www.hubfly.com/blog/solutions/how-to-fix-angular-4-api-call-issues/

Nota: Si está buscando descargar contenido de un sitio web de un tercero, esto no lo ayudará . 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");



Answer 4 Gopinath


La aplicación de una restricción CORS es una característica de seguridad definida por un servidor e implementada por un navegador .

El navegador mira la política de CORS del servidor y la respeta.

Sin embargo,la herramienta del cartero no se preocupa por la política de CORS del servidor.

Por eso el error de CORS aparece en el navegador,pero no en Postman.




Answer 5 Kamil Kiełczewski


En la investigación a continuación como API, uso http://example.com en lugar de http: // myApiUrl / login de su pregunta, porque esta primera funciona.

Supongo que su página está en http: //my-site.local: 8088 .

La razón por la que ves resultados diferentes es que el cartero:

  • establecer encabezado Host=example.com (su API)
  • NO establecer el Origin encabezado

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) . Cuando el encabezado Origin no está configurado, generalmente los servidores permiten tales solicitudes de forma predeterminada.

Enter image description here

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 dominios diferentes , y luego se produce CORS y el navegador automáticamente:

  • establece el encabezado Host=example.com (el tuyo como API)
  • establece encabezado Origin=http://my-site.local:8088 (su sitio)

(El Referer de encabezado tiene el mismo valor que Origin ). Y ahora, en la pestaña Consola y redes de Chrome, verá:

Enter image description here

Enter image description here

Cuando tenga Host != Origin esto es CORS, y cuando el servidor detecta dicha solicitud, generalmente la bloquea de manera predeterminada .

Origin=null se establece cuando abre contenido HTML desde un directorio local y envía una solicitud. La misma situación es cuando envía una solicitud dentro de un <iframe> , como en el fragmento a continuación (pero aquí el encabezado Host no está configurado en absoluto); en general, en todos los lugares donde la especificación HTML dice origen opaco, puede traducirlo a Origin=null Puede encontrar más información sobre esto aquí .

fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab

Si no utiliza una solicitud CORS simple, generalmente el navegador también envía automáticamente una solicitud de OPCIONES antes de enviar la solicitud principal; aquí encontrará más información. El fragmento a continuación 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 las solicitudes de CORS.

Aquí hay un ejemplo de configuración que activa CORS en nginx (archivo nginx.conf). Tenga mucho cuidado al configurar always/"$http_origin" para nginx y "*" para Apache; esto desbloqueará CORS de cualquier dominio.

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 activa 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"