Carga de punto final de dominio cruzado con AJAX


131

Estoy tratando de cargar una página HTML entre dominios usando AJAX, pero a menos que el tipo de datos sea "jsonp", no puedo obtener una respuesta. Sin embargo, al usar jsonp, el navegador espera un tipo de script mime pero recibe "text / html".

Mi código para la solicitud es:

$.ajax({
    type: "GET",
    url: "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P@ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute",
    dataType: "jsonp",
}).success( function( data ) {
    $( 'div.ajax-field' ).html( data );
});

¿Hay alguna forma de evitar usar jsonp para la solicitud? Ya he intentado usar el parámetro crossDomain pero no funcionó.

Si no, ¿hay alguna forma de recibir el contenido html en jsonp? Actualmente la consola dice "inesperado <" en la respuesta de jsonp.


He resuelto el problema creando un proxy.php como se explica aquí scode7.blogspot.com/2019/11/…
CodeDezk

Respuestas:


235

Notas de jQuery Ajax

  • Debido a las restricciones de seguridad del navegador, la mayoría de las solicitudes de Ajax están sujetas a la misma política de origen ; la solicitud no puede recuperar correctamente datos de un dominio, subdominio, puerto o protocolo diferente.
  • Las solicitudes de script y JSONP no están sujetas a las mismas restricciones de política de origen.

Hay algunas formas de superar la barrera entre dominios :

Hay algunos complementos que ayudan con las solicitudes entre dominios :

¡Aviso!

La mejor manera de superar este problema es crear su propio proxy en el back-end, de modo que su proxy apunte a los servicios en otros dominios, porque en el back-end no existe la misma restricción de política de origen . Pero si no puede hacerlo en el back-end, preste atención a los siguientes consejos.


¡Advertencia!

El uso de proxies de terceros no es una práctica segura, ya que pueden realizar un seguimiento de sus datos, por lo que pueden usarse con información pública, pero nunca con datos privados.


Los ejemplos de código que se muestran a continuación usan jQuery.get () y jQuery.getJSON () , ambos son métodos abreviados de jQuery.ajax ()


CORS Anywhere

CORS Anywhere es un proxy node.js que agrega encabezados CORS a la solicitud proxy.
Para usar la API, simplemente prefija la URL con la URL de la API. (Admite https : consulte el repositorio de github )

Si desea habilitar automáticamente las solicitudes de dominio cruzado cuando sea necesario, use el siguiente fragmento:

$.ajaxPrefilter( function (options) {
  if (options.crossDomain && jQuery.support.cors) {
    var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
    options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
    //options.url = "http://cors.corsproxy.io/url=" + options.url;
  }
});

$.get(
    'http://en.wikipedia.org/wiki/Cross-origin_resource_sharing',
    function (response) {
        console.log("> ", response);
        $("#viewer").html(response);
});


Cualquier origen

Cualquiera que sea el origen es un acceso jsonp de dominio cruzado . Esta es una alternativa de código abierto para anyorigin.com .

Para obtener los datos de google.com, puede usar este fragmento:

// It is good specify the charset you expect.
// You can use the charset you want instead of utf-8.
// See details for scriptCharset and contentType options: 
// http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
$.ajaxSetup({
    scriptCharset: "utf-8", //or "ISO-8859-1"
    contentType: "application/json; charset=utf-8"
});

$.getJSON('http://whateverorigin.org/get?url=' + 
    encodeURIComponent('http://google.com') + '&callback=?',
    function (data) {
        console.log("> ", data);

        //If the expected response is text/plain
        $("#viewer").html(data.contents);

        //If the expected response is JSON
        //var response = $.parseJSON(data.contents);
});


Proxy CORS

CORS Proxy es un proxy simple node.js para habilitar la solicitud CORS para cualquier sitio web. Permite que el código javascript en su sitio acceda a recursos en otros dominios que normalmente estarían bloqueados debido a la política del mismo origen.

¿Como funciona? CORS Proxy aprovecha el uso compartido de recursos de origen cruzado, que es una característica que se agregó junto con HTML 5. Los servidores pueden especificar que desean que los navegadores permitan que otros sitios web soliciten los recursos que alojan. CORS Proxy es simplemente un proxy HTTP que agrega un encabezado a las respuestas que dicen "cualquiera puede solicitar esto".

Esta es otra forma de lograr el objetivo (ver www.corsproxy.com ). Todo lo que tiene que hacer es eliminar http: // y www. desde la URL que se está representando y anteponga la URL conwww.corsproxy.com/

$.get(
    'http://www.corsproxy.com/' +
    'en.wikipedia.org/wiki/Cross-origin_resource_sharing',
    function (response) {
        console.log("> ", response);
        $("#viewer").html(response);
});


Navegador proxy CORS

Recientemente encontré este, involucra varias utilidades de Cross Origin Remote Sharing orientadas a la seguridad. Pero es una caja negra con Flash como backend.

Puede verlo en acción aquí: navegador proxy CORS
Obtenga el código fuente en GitHub: koto / cors-proxy-browser


44
También puede implementar su propia versión de WhateverOrigin.org (o transferir
EpicVoyage

1
Se puede hacer referencia a imágenes, CSS y JavaScript externo desde otro origen, por lo tanto, en la respuesta, puede pasar por la cadena HTML y reemplazar el src de recursos externos
jherax

1
hola jherax Utilicé el origen para obtener una página html (solo funcionaba para mí, utilicé yql, google, etc.) pero los caracteres no ingleses son extraños. data.contents trató de codificar, pero no ayudó
user217648

1
Hola @Miru, como dice el título: "Cargando página html de dominio cruzado con jQuery AJAX", respondí al título proporcionando algunos ejemplos usando un proxy para realizar solicitudes de dominio cruzado. Además, en respuesta a la redacción de la pregunta, proporcioné algunos enlaces para realizar solicitudes entre dominios utilizando JSONP con YQL. Los invito a leer los enlaces, son muy útiles.
jherax

1
Terminé usando el método CORS Anywhere con el $.ajaxPrefiltery funcionó muy bien. ¡Muchas gracias!
Joshua Pinter

24

Puede usar Ajax-cross-origin un complemento jQuery. Con este complemento usas jQuery.ajax()dominio cruzado. Utiliza los servicios de Google para lograr esto:

El complemento AJAX Cross Origin utiliza Google Apps Script como un proxy jSON getter donde jSONP no está implementado. Cuando establece la opción crossOrigin en true, el complemento reemplaza la url original con la dirección de Google Apps Script y la envía como parámetro de url codificado. El script de Google Apps usa los recursos de los servidores de Google para obtener los datos remotos y devolverlos al cliente como JSONP.

Es muy facíl de usar:

    $.ajax({
        crossOrigin: true,
        url: url,
        success: function(data) {
            console.log(data);
        }
    });

Puede leer más aquí: http://www.ajax-cross-origin.com/


22
En lo que a mí respecta, este complemento nunca ha funcionado. No hace nada en Chrome.
Michael

¿Cómo puedo autenticarme en el servidor?
sttaq

¡Funciona genial! La API que estoy usando no admite JSONP ni CORS, así que esto es lo único que funcionó. ¡Muchas gracias!
JP Lew

La crossOriginopción de jQuery ciertamente no hace nada para mitigar las políticas del mismo origen. Eliminaría esta respuesta si pudiera
Phil

13

Si el sitio externo no admite JSONP o CORS, su única opción es utilizar un proxy.

Cree un script en su servidor que solicite ese contenido, luego use jQuery ajax para ejecutar el script en su servidor.


5

Simplemente ponga esto en el encabezado de su página PHP y funcionará sin API:

header('Access-Control-Allow-Origin: *'); //allow everybody  

o

header('Access-Control-Allow-Origin: http://codesheet.org'); //allow just one domain 

o

$http_origin = $_SERVER['HTTP_ORIGIN'];  //allow multiple domains

$allowed_domains = array(
  'http://codesheet.org',
  'http://stackoverflow.com'
);

if (in_array($http_origin, $allowed_domains))
{  
    header("Access-Control-Allow-Origin: $http_origin");
}

Me pregunto de dónde $_SERVER['HTTP_ORIGIN']viene. No pude encontrarlo en la documentación de PHP ni en ningún otro lugar.
Zsolti

Hmm, parece que se llena solo con solicitudes AJAX. De todos modos, gracias por la respuesta.
Zsolti

0

Estoy publicando esto en caso de que alguien enfrente el mismo problema que estoy enfrentando en este momento. Tengo una impresora térmica Zebra, equipada con el servidor de impresión ZebraNet, que ofrece una interfaz de usuario basada en HTML para editar múltiples configuraciones, ver el estado actual de la impresora, etc. Necesito obtener el estado de la impresora, que se muestra en una de esas páginas html, ofrecidas por el servidor ZebraNet y, por ejemplo, alertar () un mensaje al usuario en el navegador. Esto significa que primero tengo que obtener esa página html en Javascript. Aunque la impresora está dentro de la LAN de la PC del usuario, esa misma Política de OrigenTodavía se mantiene firme en mi camino. Intenté JSONP, pero el servidor devuelve html y no he encontrado una manera de modificar su funcionalidad (si pudiera, ya habría configurado el encabezado mágico Access-control-allow-origin: *). Entonces decidí escribir una pequeña aplicación de consola en C #. Tiene que ejecutarse como administrador para que funcione correctamente; de ​​lo contrario, controla: D una excepción. Aquí hay un código:

// Create a listener.
        HttpListener listener = new HttpListener();
        // Add the prefixes.
        //foreach (string s in prefixes)
        //{
        //    listener.Prefixes.Add(s);
        //}
        listener.Prefixes.Add("http://*:1234/"); // accept connections from everywhere,
        //because the printer is accessible only within the LAN (no portforwarding)
        listener.Start();
        Console.WriteLine("Listening...");
        // Note: The GetContext method blocks while waiting for a request. 
        HttpListenerContext context;
        string urlForRequest = "";

        HttpWebRequest requestForPage = null;
        HttpWebResponse responseForPage = null;
        string responseForPageAsString = "";

        while (true)
        {
            context = listener.GetContext();
            HttpListenerRequest request = context.Request;
            urlForRequest = request.RawUrl.Substring(1, request.RawUrl.Length - 1); // remove the slash, which separates the portNumber from the arg sent
            Console.WriteLine(urlForRequest);

            //Request for the html page:
            requestForPage = (HttpWebRequest)WebRequest.Create(urlForRequest);
            responseForPage = (HttpWebResponse)requestForPage.GetResponse();
            responseForPageAsString = new StreamReader(responseForPage.GetResponseStream()).ReadToEnd();

            // Obtain a response object.
            HttpListenerResponse response = context.Response;
            // Send back the response.
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseForPageAsString);
            // Get a response stream and write the response to it.
            response.ContentLength64 = buffer.Length;
            response.AddHeader("Access-Control-Allow-Origin", "*"); // the magic header in action ;-D
            System.IO.Stream output = response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            // You must close the output stream.
            output.Close();
            //listener.Stop();

Todo lo que el usuario debe hacer es ejecutar esa aplicación de consola como administrador. Sé que es demasiado ... frustrante y complicado, pero es una solución al problema de la Política de dominio en caso de que no pueda modificar el servidor de ninguna manera.

editar: desde js hago una simple llamada ajax:

$.ajax({
                type: 'POST',
                url: 'http://LAN_IP:1234/http://google.com',
                success: function (data) {
                    console.log("Success: " + data);
                },
                error: function (e) {
                    alert("Error: " + e);
                    console.log("Error: " + e);
                }
            });

El html de la página solicitada se devuelve y se almacena en la variable de datos .


0

Para obtener el sitio externo del formulario de datos pasando usando un proxy local como lo sugiere jherax, puede crear una página php que obtenga el contenido para usted desde la URL externa respectiva y luego enviar una solicitud de obtención a esa página php.

var req = new XMLHttpRequest();
req.open('GET', 'http://localhost/get_url_content.php',false);
if(req.status == 200) {
   alert(req.responseText);
}

como proxy php puedes usar https://github.com/cowboy/php-simple-proxy


0

Su URLno funciona en estos días, pero su código puede ser actualizado con esta solución de trabajo:

var url = "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P@ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute";

url = 'https://google.com'; // TEST URL

$.get("https://images"+~~(Math.random()*33)+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=" + encodeURI(url), function(data) {
    $('div.ajax-field').html(data);
});
<div class="ajax-field"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


-2

Necesita un proxy CORS que delegue su solicitud desde su navegador al servicio solicitado con los encabezados CORS apropiados . La lista de dichos servicios se encuentra en el fragmento de código a continuación. También puede ejecutar el fragmento de código proporcionado para ver el ping a dichos servicios desde su ubicación.

$('li').each(function() {
  var self = this;
  ping($(this).text()).then(function(delta) {
    console.log($(self).text(), delta, ' ms');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/jdfreder/pingjs/c2190a3649759f2bd8569a72ae2b597b2546c871/ping.js"></script>
<ul>
  <li>https://crossorigin.me/</li>
  <li>https://cors-anywhere.herokuapp.com/</li>
  <li>http://cors.io/</li>
  <li>https://cors.5apps.com/?uri=</li>
  <li>http://whateverorigin.org/get?url=</li>
  <li>https://anyorigin.com/get?url=</li>
  <li>http://corsproxy.nodester.com/?src=</li>
  <li>https://jsonp.afeld.me/?url=</li>
  <li>http://benalman.com/code/projects/php-simple-proxy/ba-simple-proxy.php?url=</li>
</ul>


11
Esto no responde la pregunta de ninguna manera.
0xc0de

@ 0xc0de finalmente escribí la respuesta.
galeksandrp

-7

Lo averigué. Usé esto en su lugar.

$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle');

El código que usaste allí es irrelevante. Lo que importa son los encabezados CORS del lado del servidor.
Quentin
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.