Dominio cruzado jQuery AJAX


477

Aquí hay dos páginas, test.php y testserver.php.

test.php

<script src="scripts/jq.js" type="text/javascript"></script>
<script>
    $(function() {
        $.ajax({url:"testserver.php",
            success:function() {
                alert("Success");
            },
            error:function() {
                alert("Error");
            },
            dataType:"json",
            type:"get"
        }
    )})
</script>

testserver.php

<?php
$arr = array("element1",
             "element2",
             array("element31","element32"));
$arr['name'] = "response";
echo json_encode($arr);
?>

Ahora mi problema: cuando ambos archivos están en el mismo servidor (localhost o servidor web), funciona y alert("Success")se llama; Si está en diferentes servidores, lo que significa que testserver.php en el servidor web y test.php en localhost, no funciona y se alert("Error")está ejecutando. Incluso si la URL dentro de ajax se cambia a http://domain.com/path/to/file/testserver.php


38
Para las personas que pasan por aquí. Lea esto para tener una idea de cómo funcionan las llamadas de JavaScript entre dominios stackoverflow.com/a/11736771/228656
Abdul Munim

1
Escribí una respuesta para esta pregunta aquí: Cargando la página html de dominio cruzado con jQuery AJAX - la última, es compatible con https
jherax

Respuestas:


412

Usa JSONP .

jQuery:

$.ajax({
     url:"testserver.php",
     dataType: 'jsonp', // Notice! JSONP <-- P (lowercase)
     success:function(json){
         // do stuff with json (in this case an array)
         alert("Success");
     },
     error:function(){
         alert("Error");
     }      
});

PHP:

<?php
$arr = array("element1","element2",array("element31","element32"));
$arr['name'] = "response";
echo $_GET['callback']."(".json_encode($arr).");";
?>

El eco puede estar equivocado, ha pasado un tiempo desde que usé php. En cualquier caso, debe dar salida a callbackName('jsonString')las cotizaciones. jQuery pasará su propio nombre de devolución de llamada, por lo que debe obtenerlo de los parámetros GET.

Y como Stefan Kendall publicó, $ .getJSON () es un método abreviado, pero luego debe agregar 'callback=?'a la url como parámetro GET (sí, el valor es?, JQuery reemplaza esto con su propio método de devolución de llamada generado).


2
¿Por qué necesitas regresar en callbackName('/* json */')lugar de callbackName(/* json */)?
Eric

3
@eric la devolución de llamada espera una cadena JSON. Teóricamente, un objeto podría funcionar también, pero no estoy seguro de cómo responde jQuery a esto, podría arrojar un error o fallar en silencio.
BGerrissen

Recibo el siguiente error. SyntaxError: falta; antes de la declaración {"ResultCode": 2}. Donde {"ResultCode": 2} es la respuesta. Por favor aconséjame.
user2003356

@ user2003356 parece que está devolviendo JSON simple en lugar de JSONP. Debe devolver algo como: callbackFunction ({"ResultCode": 2}). jQuery agrega el parámetro GET 'devolución de llamada' a la solicitud, ese es el nombre de la función de devolución de llamada que utiliza jquery y debe agregarse a la respuesta.
BGerrissen

2
Es 2016. CORS es ahora un estándar ampliamente admitido, a diferencia de JSONP, que solo puede describirse como un hack. La respuesta de @ joshuarh a continuación debería ser la preferida ahora.
Vicky Chijwani

202

JSONP es una buena opción, pero hay una manera más fácil. Simplemente puede configurar el Access-Control-Allow-Originencabezado en su servidor. Al configurarlo, *se aceptarán solicitudes AJAX entre dominios de cualquier dominio. ( https://developer.mozilla.org/en/http_access_control )

El método para hacerlo variará de un idioma a otro, por supuesto. Aquí está en Rails:

class HelloController < ApplicationController
  def say_hello
    headers['Access-Control-Allow-Origin'] = "*"
    render text: "hello!"
  end
end

En este ejemplo, la say_helloacción aceptará solicitudes AJAX de cualquier dominio y devolverá una respuesta de "¡hola!".

Aquí hay un ejemplo de los encabezados que podría devolver:

HTTP/1.1 200 OK 
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: text/html; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "c4ca4238a0b923820dcc509a6f75849b"
X-Runtime: 0.913606
Content-Length: 6
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date: Thu, 01 Mar 2012 20:44:28 GMT
Connection: Keep-Alive

Tan fácil como es, tiene algunas limitaciones de navegador. Ver http://caniuse.com/#feat=cors .


12
Jsonp no admitió publicar, poner y eliminar. Tu solución funciona muy bien.
TonyTakeshi

35
en el encabezado PHP ("Access-Control-Allow-Origin: *");
SparK

99
@Warrior Si está utilizando el .post()método de jQuery, debe habilitar la compatibilidad entre dominios en jQuery. Se realiza con esto: $.support.cors = true.
Friederike

21
¿Cuáles son las implicaciones de seguridad de configurar un servidor de esta manera?
Jon Schneider

19
Sería mejor permitir solo aquellos dominios con los que desea compartir los datos en lugar de usar el wilcard "*".
Sebastián Grignoli

32

Puede controlar esto a través del encabezado HTTP agregando Access-Control-Allow-Origin . Al establecerlo en * se aceptarán solicitudes AJAX de dominio cruzado de cualquier dominio.

Usar PHP es realmente simple, solo agregue la siguiente línea en el script al que desea tener acceso fuera de su dominio:

header("Access-Control-Allow-Origin: *");

No olvide habilitar el módulo mod_headers en httpd.conf.


Salvaste mi día.
NomanJaved

20

Debes echar un vistazo a la Política del mismo origen :

En informática, la misma política de origen es un concepto de seguridad importante para varios lenguajes de programación del lado del navegador, como JavaScript. La política permite que los scripts que se ejecutan en páginas que se originan en el mismo sitio accedan a los métodos y propiedades de los demás sin restricciones específicas, pero impide el acceso a la mayoría de los métodos y propiedades en las páginas de diferentes sitios.

Para que pueda obtener datos, tiene que ser:

Mismo protocolo y host

Debe implementar JSONP para solucionarlo.


17

Tuve que cargar la página web desde el disco local "archivo: /// C: /test/htmlpage.html", llamar a la url "http: //localhost/getxml.php" y hacer esto en los navegadores IE8 + y Firefox12 +, usar jQuery v1 .7.2 lib para minimizar el código repetitivo. Después de leer docenas de artículos finalmente lo descubrí. Aquí está mi resumen.

  • la secuencia de comandos del servidor (.php, .jsp, ...) debe devolver el encabezado de respuesta http Access-Control-Allow-Origin: *
  • antes de usar jQuery ajax establezca este indicador en javascript: jQuery.support.cors = true;
  • Puede establecer la bandera una o cada vez antes de usar la función jQuery ajax
  • ahora puedo leer documentos .xml en IE y Firefox. Otros navegadores que no probé.
  • El documento de respuesta puede ser simple / text, xml, json o cualquier otra cosa

Aquí hay un ejemplo de llamada jQuery ajax con algunos sysouts de depuración.

jQuery.support.cors = true;
$.ajax({
    url: "http://localhost/getxml.php",
    data: { "id":"doc1", "rows":"100" },
    type: "GET",
    timeout: 30000,
    dataType: "text", // "xml", "json"
    success: function(data) {
        // show text reply as-is (debug)
        alert(data);

        // show xml field values (debug)
        //alert( $(data).find("title").text() );

        // loop JSON array (debug)
        //var str="";
        //$.each(data.items, function(i,item) {
        //  str += item.title + "\n";
        //});
        //alert(str);
    },
    error: function(jqXHR, textStatus, ex) {
        alert(textStatus + "," + ex + "," + jqXHR.responseText);
    }
});

1
Escribí una respuesta para esta pregunta aquí: Cargando página html de dominio cruzado con jQuery AJAX - la última, es compatible con https
jherax

Para el punto más claro: en PHP agregue esta línea al script:header("Access-Control-Allow-Origin: *");
T30

1
@whome muchas gracias por tu respuesta. Me ayudaste mucho. Salud.
Luis Milanese

10

Es cierto que la política del mismo origen evita que JavaScript realice solicitudes en todos los dominios, pero la especificación CORS permite el tipo de acceso a la API que está buscando y es compatible con el lote actual de los principales navegadores.

Vea cómo habilitar el intercambio de recursos de origen cruzado para el cliente y el servidor:

http://enable-cors.org/

"Cross-Origin Resource Sharing (CORS) es una especificación que permite un acceso verdaderamente abierto a través de los límites del dominio. Si sirve contenido público, considere usar CORS para abrirlo para el acceso universal de JavaScript / navegador".



9

Yo uso el servidor Apache, así que he usado el módulo mod_proxy. Habilitar módulos:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Luego añade:

ProxyPass /your-proxy-url/ http://service-url:serviceport/

Finalmente, pase proxy-url a su script.




4

De los documentos de Jquery ( enlace ):

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

  • Las solicitudes de script y JSONP no están sujetas a las mismas restricciones de política de origen.

Por lo tanto, supongo que debe usar jsonp para la solicitud. Pero no lo he intentado yo mismo.


2

Sé 3 maneras de resolver su problema:

  1. Primero, si tiene acceso a ambos dominios, puede permitir el acceso a todos los demás dominios utilizando:

    header("Access-Control-Allow-Origin: *");

    o simplemente un dominio agregando código debajo del archivo .htaccess:

    <FilesMatch "\.(ttf|otf|eot|woff)$"> <IfModule mod_headers.c> SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.net|dev02.otherdomain.net)$" AccessControlAllowOrigin=$0 Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin </IfModule> </FilesMatch>

  2. puede tener una solicitud ajax a un archivo php en su servidor y manejar la solicitud a otro dominio utilizando este archivo php.

  3. puedes usar jsonp, porque no necesita permiso. para esto puedes leer la respuesta de nuestro amigo @BGerrissen.

0

Para Microsoft Azure, es ligeramente diferente.

Azure tiene una configuración CORS especial que debe establecerse. Es esencialmente lo mismo detrás de escena, pero simplemente establecer el encabezado que menciona joshuarh no funcionará. La documentación de Azure para habilitar el dominio cruzado se puede encontrar aquí:

https://docs.microsoft.com/en-us/azure/app-service-api/app-service-api-cors-consume-javascript

Estuve jugando con esto durante unas horas antes de darme cuenta de que mi plataforma de alojamiento tenía esta configuración especial.


0

funciona, todo lo que necesitas:

PHP:

header('Access-Control-Allow-Origin: http://www.example.com');
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');

JS (jQuery ajax):

var getWBody = $.ajax({ cache: false,
        url: URL,
        dataType : 'json',
        type: 'GET',
        xhrFields: { withCredentials: true }
});
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.