jquery razón ¿Por qué mi JavaScript obtiene un error de "No 'Access-Control-Allow-Origin' presente en el recurso solicitado" cuando Postman no lo hace?




wordpress access control allow origin (24)

Estoy tratando de hacer la autorización utilizando JavaScript conectándome a la API RESTful incorporada en Flask . Sin embargo, cuando hago la solicitud, aparece el siguiente error:

XMLHttpRequest no puede cargar http: // myApiUrl / login . No hay ningún encabezado 'Access-Control-Allow-Origin' presente en el recurso solicitado. Por tanto, no se permite el acceso al origen 'nulo'.

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);
    });

CORS es para ti.

CORS es "Intercambio de recursos de origen cruzado" y es una forma de enviar una solicitud de dominio cruzado. Ahora, XMLHttpRequest2 y Fetch API son compatibles con CORS.

Pero tiene sus límites. El servidor debe especificar específicamente el acceso-control-permitir-origen , y no se puede configurar en '*'.

Y si desea que cualquier origen pueda enviarle una solicitud, necesita JSONP (también necesita configurar Access-Control-Allow-Origin , pero puede ser '*').

Si no sabe qué elegir, creo que necesita un componente totalmente funcional para hacerlo. Permítanme presentarles un componente simple catta

Si está utilizando un navegador moderno (> Internet Explorer9, Chrome, Firefox, Edge, etc.), es muy recomendable que use un componente simple pero hermoso, catta . No tiene dependencias, tiene menos de 3 KB y es compatible con Fetch, Ajax y JSONP con la misma sintaxis y opciones simples.

catta('./data/simple.json').then(function (res) {
  console.log(res);
});

También admite todo el camino para importar a su proyecto, como el módulo ES6, CommonJS e incluso <script>en HTML.


Pregunta popular: otra cosa que ver si has leído hasta aquí y nada más ha ayudado. Si tiene un CDN como Akamai, Limelight o similar, es posible que desee verificar la clave de caché que tiene para el URI del recurso. Si no incluye el valor del encabezado de Origen, es posible que esté devolviendo una respuesta en caché cuando se solicite desde otro Origen. Acabamos de pasar medio día depurando esto. La configuración de CDN se actualizó para incluir solo el valor de Origen para algunos dominios seleccionados que son nuestros y establecerlo en nulo para todos los demás. Esto parece funcionar y permite que los navegadores de nuestros dominios conocidos vean nuestros recursos. Ciertamente, todas las demás respuestas son requisitos previos para llegar hasta aquí, pero si el CDN es el primer salto desde su navegador, esto es algo para revisar.

En nuestro caso, pudimos ver algunas solicitudes para llegar a nuestro servicio, pero no casi el volumen que el sitio estaba enviando. Eso nos apuntó a la CDN. Pudimos regresar y ver que la solicitud original fue atendida desde una solicitud directa, no era parte de una llamada AJAX del navegador y el encabezado de respuesta Access-Control-Allow-Origin no fue incluido. Al parecer, el CDN guardó en caché este valor. El ajuste de configuración de CDN de Akamai para considerar el valor del encabezado de solicitud de Origen como parte de la coincidencia parece haberlo hecho funcionar para nosotros.


Tuve un problema con esto cuando usé AngularJS para acceder a mi API. La misma solicitud funcionó en SoapUI 5.0 y ColdFusion. Mi método GET ya tenía el encabezado Access-Control-Allow-Origin.

Descubrí que AngularJS realiza una solicitud de OPCIONES de "prueba" . ColdFusion, de forma predeterminada, genera el método OPCIONES, pero no tiene mucho, específicamente estos encabezados. El error se generó en respuesta a esa llamada de OPCIONES, y no a mi llamada intencional a GET. Después de agregar el método OPCIONES a mi API, el problema se resolvió.

<cffunction name="optionsMethod" access="remote" output="false" returntype="any" httpmethod="OPTIONS" description="Method to respond to AngularJS trial call">
    <cfheader name="Access-Control-Allow-Headers" value="Content-Type,x-requested-with,Authorization,Access-Control-Allow-Origin"> 
    <cfheader name="Access-Control-Allow-Methods" value="GET,OPTIONS">      
    <cfheader name="Access-Control-Allow-Origin" value="*">      
    <cfheader name="Access-Control-Max-Age" value="360">        
</cffunction>

Para completar, Apache permite cors:

Header set Access-Control-Allow-Origin "http://www.allowonlyfromthisurl.com"
Header set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header set Access-Control-Max-Age "1000"
Header set Access-Control-Allow-Headers "x-requested-with, Content-Type, Accept-Encoding, Accept-Language, Cookie, Referer"

Para el servidor Ruby on Rails application_controller.rb, agregue esto:

after_action :cors_set_access_control_headers

def cors_set_access_control_headers
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
  headers['Access-Control-Allow-Headers'] = '*'
end

Puede evitar el problema utilizando YQL para enviar la solicitud a través de los servidores de Yahoo. Es sólo unas pocas líneas de código:

var yql_url = 'https://query.yahooapis.com/v1/public/yql';
var url = 'your api url';

$.ajax({
    'url': yql_url,
    'data': {
        'q': 'SELECT * FROM json WHERE url="'+url+'"',
        'format': 'json',
        'jsonCompat': 'new',
    },
    'dataType': 'jsonp',
    'success': function(response) {
        console.log(response);
    },
});

Aquí está el enlace con una explicación: https://vverma.net/fetch-any-json-using-jsonp-and-yql.html


Muchas veces esto me pasa de javascript a mi php api, por una de las pocas razones. Me olvido de poner el <?php header('Access-Control-Allow-Origin: *'); ?es uno. Esto es útil para el acceso de subdominio cruzado. Otra razón es que en la solicitud jQuery ajax estoy especificando un tipo de datos específico y devolviendo un tipo de datos diferente, por lo que produce un error.

El último y más importante razonamiento para este error es que hay un error de análisis en la página que está solicitando. Si presiona la url de la página en su navegador, es más que probable que vea un error de análisis y tendrá un número de línea para solucionar el problema.

Espero que esto ayude a alguien. Cada vez me tomaba un tiempo depurar esto y me gustaría tener una lista de verificación de cosas para verificar.


Prueba XDomain ,

Resumen: una alternativa de JavaScript CORS / polyfill puro. No se requiere configuración del servidor: solo agregue un proxy.html en el dominio con el que desea comunicarse. Esta biblioteca usa XHook para enlazar todos los XMLHttpRequest , por lo que XDomain debería funcionar junto con cualquier biblioteca.


https://github.com/Rob--W/cors-anywhere/ proporciona el código (Node.js) que puede usar para configurar y ejecutar su propio proxy CORS. Se mantiene activamente y proporciona una serie de características para controlar el comportamiento del proxy más allá del simple envío de los encabezados de respuesta de Control-Control correctos Access-Control-* .

developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS tiene detalles para explicar cómo los navegadores manejan las solicitudes de origen cruzado que hacen las aplicaciones web del lado del cliente desde JavaScript y de qué encabezados debe configurar el envío. El servidor al que se hace la solicitud, si puede.

En el caso de que un sitio del que deba realizar una solicitud y obtener una respuesta no devuelva el encabezado de respuesta de Access-Control-Allow-Origin , los navegadores siempre bloquearán las solicitudes de origen cruzado que le envíe directamente su cliente. código JavaScript de lado de trabajar. Y así, si el sitio no es uno para el que controla y puede configurar el comportamiento, lo único que funcionará en ese caso es enviar las solicitudes, ya sea a través de su propio proxy, usted mismo o un proxy abierto.

Como se mencionó en otros comentarios aquí, hay buenas razones para no confiar en un proxy abierto con sus solicitudes. Dicho esto, si sabe lo que está haciendo y decide que un proxy abierto funciona para sus necesidades, https://cors-anywhere.herokuapp.com/ es uno que está disponible de manera confiable, se mantiene activamente y que ejecuta una instancia de https://github.com/Rob--W/cors-anywhere/ code.

Al igual que con otros proxies abiertos mencionados aquí (algunos de los cuales al menos ya no parecen estar disponibles), la forma en que funciona es que, en lugar de que su código de cliente envíe una solicitud directamente a, por ejemplo, http://foo.com lo envía a https://cors-anywhere.herokuapp.com/http://foo.com y el proxy agrega los encabezados Access-Control-* a la respuesta que ve el navegador.


Tuve la siguiente configuración, que resultó en el mismo error, al solicitar respuestas del servidor.

Lado del servidor: SparkJava -> proporciona la API REST
Lado del cliente: ExtJs6 -> proporciona la representación del navegador

En el lado del servidor tuve que agregar esto a la respuesta:

Spark.get("/someRestCallToSpark", (req, res) -> {
    res.header("Access-Control-Allow-Origin", "*"); //important, otherwise its not working 
    return "some text";
 });

En el lado del cliente tuve que agregar esto a la solicitud:

Ext.Ajax.request({
    url: "http://localhost:4567/someRestCallToSpark",
    useDefaultXhrHeader: false, //important, otherwise its not working
    success: function(response, opts) {console.log("success")},
    failure: function(response, opts) {console.log("failure")}
});

No hay ningún encabezado 'Access-Control-Allow-Origin' presente en el recurso solicitado. Por lo tanto, el origen " https://sx.xyz.com " no está permitido el acceso.

También tuve un problema similar con el intercambio de datos entre dominios en la respuesta Ajax como error indefinido . Pero la respuesta en el encabezado fue Código de estado: 200 OK

Failed to load https://www.Domain.in/index.php?route=api/synchronization/checkapikey:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'https://sx.xyz.in' is therefore not allowed access.

La solución para evitarlo : en mi caso, fue llamar a la función checkapikey () a través de Ajax a otro dominio y obtener la respuesta con datos donde se realizó la llamada:

if (($this->request->server['REQUEST_METHOD'] == 'POST') && isset($this->request->server['HTTP_ORIGIN'])) {

        $this->response->addHeader('Access-Control-Allow-Origin: ' . $this->request->server['HTTP_ORIGIN']);
        $this->response->addHeader('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
        $this->response->addHeader('Access-Control-Max-Age: 1000');
        $this->response->addHeader('Access-Control-Allow-Credentials: true');
        $this->response->addHeader('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');

        $headers = getallheaders();
...
}

Pude resolver con éxito (en mi caso para las fuentes) usando htaccess pero obviamente, OP está pidiendo algo diferente. Pero puede usar el patrón de FileMatch y agregar cualquier tipo de extensión para que no le dé un error de cros.

<IfModule mod_headers.c>
  <FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css)$">
    Header set Access-Control-Allow-Origin "*"
  </FilesMatch>
</IfModule>

https://httpd.apache.org/docs/2.4/mod/core.html#filesmatch


Para la API de GoLang:

Primero, puede echar un vistazo a MDN CORS Doc para saber qué es CORS. Por lo que sé, CORS trata sobre si se debe permitir que Origin Of Request acceda a Server Resource o no.

Y puede restringir qué origen de solicitud puede acceder al servidor configurando Access-Control-Allow-Origin en Header of Server Response.

Por ejemplo, la configuración del siguiente encabezado en Server Response significa que solo la solicitud enviada desde http://foo.example puede acceder a su servidor:

Access-Control-Allow-Origin: http://foo.example

y siguiendo la solicitud de permiso enviada desde cualquier origen (o dominio):

Access-Control-Allow-Origin: *

Y como sé en el mensaje de error, requested resource significa recurso del servidor, por lo que No 'Access-Control-Allow-Origin' header is present on the requested resource. significa que no configuró el encabezado Access-Control-Allow-Origin en su respuesta del servidor, o tal vez lo configuró, pero el origen de la solicitud no está en la lista de Access-Control-Allow-Origin por lo que no se permite el acceso a la solicitud

No hay ningún encabezado 'Access-Control-Allow-Origin' presente en el recurso solicitado. Por tanto, no se permite el acceso al origen 'nulo'.

En GoLang, uso el paquete gorilla/mux para crear un servidor de API en localhost:9091 , y permito a CORS agregar "Access-Control-Allow-Origin", "*" al encabezado de la respuesta:

func main() { // API Server Code
    router := mux.NewRouter()
    // API route is /people,
    //Methods("GET", "OPTIONS") means it support GET, OPTIONS
    router.HandleFunc("/people", GetPeople).Methods("GET", "OPTIONS")
    log.Fatal(http.ListenAndServe(":9091", router))
}

// Method of '/people' route
func GetPeople(w http.ResponseWriter, r *http.Request) {

    // Allow CORS by setting * in sever response
    w.Header().Set("Access-Control-Allow-Origin", "*")

    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    json.NewEncoder(w).Encode("OKOK")
}

Y utilizo JavaScript en el cliente, en localhost:9092 solicitud de Chrome puede obtener con éxito "OKOK" desde el servidor localhost:9091 .

function GetPeople() {
    try {
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", "http://localhost:9091/people", false);
        xhttp.setRequestHeader("Content-type", "text/html");
        xhttp.send();
        var response = JSON.parse(xhttp.response);
        alert(xhttp.response);
    }
    catch (error) {
        alert(error.message);
    }
}

Además, puedes verificar el encabezado de tu solicitud / respuesta con herramientas como Fiddler .


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

Cuando está utilizando un cartero, 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 limitados por la misma política de origen. Las extensiones no son tan limitadas. Una extensión puede comunicarse con servidores remotos fuera de su origen, siempre que primero solicite permisos de origen cruzado.


Basándome en la respuesta de shruti , he creado un acceso directo del navegador Chrome con los argumentos necesarios:


Esta no es una solución para la producción o cuando la aplicación debe mostrarse al cliente, esto solo es útil cuando la IU y el desarrollo de Backend están en servidores diferentes y en producción están en el mismo servidor. Por ejemplo: al desarrollar una interfaz de usuario para cualquier aplicación, si es necesario probarlo localmente apuntando a un servidor backend, en ese escenario esta es la solución perfecta. Para la corrección de producción, los encabezados CORS deben agregarse al servidor backend para permitir el acceso de origen cruzado.

La forma más sencilla es simplemente agregar la extensión en google chrome para permitir el acceso mediante CORS.

( https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en-US )

Simplemente habilite esta extensión siempre que desee permitir el acceso a ninguna solicitud de encabezado 'access-control-allow-origin' .

O

En Windows, pega este comando en la ventana de ejecución

chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security

Esto abrirá un nuevo navegador Chrome que permitirá el acceso a ninguna solicitud de encabezado 'acceso-control-permitir-origen' .


En mi caso, estaba usando la aplicación JEE7 JAX-RS y los siguientes trucos funcionaron perfectamente para mí:

@GET
    @Path("{id}")
    public Response getEventData(@PathParam("id") String id) throws FileNotFoundException {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("/eventdata/" + id + ".json");
        JsonReader jsonReader = Json.createReader(inputStream);
        return Response.ok(jsonReader.readObject()).header("Access-Control-Allow-Origin", "*").build();
    }

Tal vez sea un poco complicado, pero puede utilizar un servidor web para enrutar la solicitud. Con nodejs no tienes este problema. No soy un experto en nodos js. Así que no sé si este es un código limpio.

Pero esto funciona para mi

Aquí hay un pequeño ejemplo:

NODO JS

var rp = require('request-promise');
var express = require('express'),
    app = express(),
    port = process.env.PORT || 3000;
var options = {
    method: 'POST',
    uri: 'http://api.posttestserver.com/post',
    body: {
        some: 'payload'
    },
    json: true // Automatically stringifies the body to JSON
};
app.get('/', function (req, res) {
        rp(options)
        .then(function (parsedBody) {
            res.send(parsedBody)
        })
        .catch(function (err) {
            res.send(err)
        });
});
app.listen(port);

JS

axios.get("http://localhost:3000/").then((res)=>{
    console.log('================res====================');
    console.log(res);
    console.log('====================================');
})

En mi sitio web (basado en .NET) acabo de agregar esto:

<system.webServer>
 <httpProtocol>  
    <customHeaders>  
     <add name="Access-Control-Allow-Origin" value="*" />  
     <add name="Access-Control-Allow-Headers" value="Content-Type" />  
     <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />  
    </customHeaders>  
  </httpProtocol>         
</system.webServer>

Muchas gracias a this video.


Es muy sencillo de resolver si está utilizando PHP . Simplemente agregue el siguiente script al comienzo de su página PHP que maneja la solicitud:

<?php header('Access-Control-Allow-Origin: *'); ?>

Advertencia: Esto contiene un problema de seguridad para su archivo PHP al que los atacantes podrían llamar. tiene que usar sesiones y cookies para la autenticación para evitar que su archivo / servicio contra este ataque. Su servicio es vulnerable a la falsificación de solicitudes entre sitios (CSRF).

Si está utilizando Node-red , debe permitir CORS en el archivo node-red/settings.js anulando 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 Entity Framework , parece que este error a veces se producirá incluso si tiene CORS habilitado. Me di cuenta de que el error se produjo debido a una finalización faltante de la consulta. Espero que esto ayude a otros en la misma situación.

El siguiente código puede lanzar el XMLHttpRequest cannot load http://myApiUrl/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. XMLHttpRequest cannot load http://myApiUrl/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. error:

using (DBContext db = new DBContext())
{
    return db.Customers.Select(x => new
    {
        Name = x.Name,
        CustomerId = x.CustomerId,
    });
}

Para solucionarlo, se requiere una llamada de finalización como .ToList() o .FirstOrDefault() al final de la consulta, así:

using (DBContext db = new DBContext())
{
    return db.Customers.Select(x => new
    {
        Name = x.Name,
        CustomerId = x.CustomerId,
    }).ToList();
}

Si está utilizando Node.js , inténtelo:

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

Más información: CORS en ExpressJS


Si recibe este mensaje de error del navegador:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '…' is therefore not allowed access

cuando intente realizar una solicitud Ajax POST / GET a un servidor remoto que está fuera de su control, olvídese de esta sencilla solución:

<?php header('Access-Control-Allow-Origin: *'); ?>

Realmente necesita, especialmente si solo usa JavaScript para realizar la solicitud de Ajax, un proxy interno que toma su consulta y la envía al servidor remoto.

Primero en su código JavaScript, realice una llamada Ajax a su propio servidor, algo como:

$.ajax({
    url: yourserver.com/controller/proxy.php,
    async: false,
    type: "POST",
    dataType: "json",
    data: data,
    success: function (result) {
        JSON.parse(result);
    },
    error: function (xhr, ajaxOptions, thrownError) {
        console.log(xhr);
    }
});

Luego, cree un archivo PHP simple llamado proxy.php para envolver sus datos POST y adjúntelos al servidor remoto de URL como parámetros. Te doy un ejemplo de cómo evito este problema con la API de búsqueda de hoteles de Expedia:

if (isset($_POST)) {
  $apiKey = $_POST['apiKey'];
  $cid = $_POST['cid'];
  $minorRev = 99;

  $url = 'http://api.ean.com/ean-services/rs/hotel/v3/list?' . 'cid='. $cid . '&' . 'minorRev=' . $minorRev . '&' . 'apiKey=' . $apiKey;

  echo json_encode(file_get_contents($url));
 }

Haciendo:

echo json_encode(file_get_contents($url));

Simplemente estás haciendo la misma consulta, pero en el lado del servidor, después de eso, debería funcionar bien.

Responde copiado y pegado desde NizarBsb


Si puede tratar con JSON a cambio, intente usar JSONP (note la P al final) para hablar entre dominios:

$.ajax({
  type: "POST",
  dataType: 'jsonp',
  ...... etc ......

Obtenga más información sobre cómo trabajar con JSONP here :

El advenimiento de JSONP, esencialmente un truco de secuencias de comandos consensual entre sitios, ha abierto la puerta a poderosos mashups de contenido. Muchos sitios destacados proporcionan servicios JSONP, lo que le permite acceder a su contenido a través de una API predefinida.







flask-restless