jQuery AJAX interdominio


477

Ecco due pagine, test.php e 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);
?>

Ora il mio problema: quando entrambi questi file si trovano sullo stesso server (localhost o web server), funziona e alert("Success")viene chiamato; Se si trova su server diversi, significa testerver.php sul server web e test.php su localhost, non funziona e si alert("Error")sta eseguendo. Anche se l'URL all'interno di Ajax viene modificato in http://domain.com/path/to/file/testserver.php


38
Per le persone che si fermano. Leggi questo per avere un'idea di come funzionano le chiamate javascript tra domini stackoverflow.com/a/11736771/228656
Abdul Munim

1
Ho scritto una risposta per questa domanda qui: caricamento della pagina html tra domini con jQuery AJAX - l'ultimo, supporta https
jherax,

Risposte:


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).");";
?>

L'eco potrebbe essere sbagliata, è da un po 'che non uso php. In ogni caso è necessario emettere callbackName('jsonString')notare i preventivi. jQuery passerà il proprio nome di callback, quindi è necessario ottenerlo dai parametri GET.

E come ha pubblicato Stefan Kendall, $ .getJSON () è un metodo abbreviato, ma quindi è necessario aggiungere 'callback=?'all'URL come parametro GET (sì, valore è?, JQuery lo sostituisce con il proprio metodo di callback generato).


2
Perché devi tornare callbackName('/* json */')invece di callbackName(/* json */)?
Eric,

3
@eric il callback prevede una stringa JSON. Teoricamente, anche un oggetto potrebbe funzionare, ma non è sicuro di come jQuery risponda a questo, potrebbe generare un errore o fallire silenziosamente.
BGerrissen,

Ricevo il seguente errore. SintassiErrore: mancante; prima dell'istruzione {"ResultCode": 2}. Dove {"ResultCode": 2} è la risposta. Per favore, consiglio.
user2003356

@ user2003356 sembra che tu stia restituendo JSON semplice anziché JSONP. Devi restituire qualcosa del tipo: callbackFunction ({"ResultCode": 2}). jQuery aggiunge il parametro GET 'callback' alla richiesta, questo è il nome della funzione di callback che jquery utilizza e deve essere aggiunto alla risposta.
BGerrissen,

2
È il 2016. CORS è ora uno standard ampiamente supportato, al contrario di JSONP che può essere descritto solo come un hack. La risposta di @ joshuarh qui sotto dovrebbe essere quella preferita ora.
Vicky Chijwani,

202

JSONP è una buona opzione, ma esiste un modo più semplice. Puoi semplicemente impostare l' Access-Control-Allow-Originintestazione sul tuo server. L'impostazione su *accetterà le richieste AJAX tra domini da qualsiasi dominio. ( https://developer.mozilla.org/en/http_access_control )

Il metodo per farlo varierà da una lingua all'altra, ovviamente. Eccolo in Rails:

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

In questo esempio, l' say_helloazione accetterà le richieste AJAX da qualsiasi dominio e restituirà una risposta di "ciao!".

Ecco un esempio delle intestazioni che potrebbe restituire:

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

Facile com'è, ha alcune limitazioni del browser. Vedi http://caniuse.com/#feat=cors .


12
Jsonp non supportava il post, l'inserimento e l'eliminazione. La tua soluzione funziona alla grande.
TonyTakeshi,

35
nell'intestazione PHP ("Access-Control-Allow-Origin: *");
SparK,

9
@Warrior Se stai utilizzando il .post()metodo jQuery devi abilitare il supporto interdominio in jQuery. E 'fatto con questo: $.support.cors = true.
Friederike,

21
Quali sono le implicazioni di sicurezza della configurazione di un server in questo modo?
Jon Schneider,

19
Sarebbe meglio consentire solo quei domini con cui si desidera condividere i dati invece di utilizzare la wilcard "*".
Sebastián Grignoli,

32

Puoi controllarlo tramite intestazione HTTP aggiungendo Access-Control-Allow-Origin . Impostandolo su * si accettano richieste AJAX tra domini da qualsiasi dominio.

Usare PHP è davvero semplice, basta aggiungere la seguente riga nello script a cui si desidera avere accesso al di fuori del proprio dominio:

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

Non dimenticare di abilitare il modulo mod_headers in httpd.conf.


mi hai salvato la giornata.
NomanJaved

20

Devi dare un'occhiata alla stessa politica di origine :

Nell'informatica, la stessa politica di origine è un importante concetto di sicurezza per numerosi linguaggi di programmazione lato browser, come JavaScript. La politica consente agli script in esecuzione su pagine provenienti dallo stesso sito di accedere a metodi e proprietà reciproci senza restrizioni specifiche, ma impedisce l'accesso alla maggior parte dei metodi e delle proprietà su più pagine di siti diversi.

Per poter ottenere i dati, devono essere:

Stesso protocollo e host

È necessario implementare JSONP per aggirare il problema.


17

Ho dovuto caricare la pagina Web dal disco locale "file: /// C: /test/htmlpage.html", chiamare l'URL "http: //localhost/getxml.php" e farlo in browser IE8 + e Firefox12 +, usare jQuery v1 .7.2 lib per minimizzare il codice del boilerplate. Dopo aver letto dozzine di articoli, finalmente ho capito. Ecco il mio riassunto.

  • lo script del server (.php, .jsp, ...) deve restituire l'intestazione della risposta http Access-Control-Allow-Origin: *
  • prima di usare jQuery ajax imposta questo flag in javascript: jQuery.support.cors = true;
  • è possibile impostare flag una o ogni volta prima di utilizzare la funzione jQuery ajax
  • ora posso leggere il documento .xml in IE e Firefox. Altri browser che non ho testato.
  • il documento di risposta può essere semplice / testo, xml, json o qualsiasi altra cosa

Ecco un esempio di chiamata jQuery ajax con alcuni sysout di debug.

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
Ho scritto una risposta a questa domanda qui: caricamento della pagina html tra domini con jQuery AJAX - l'ultimo, supporta https
jherax,

Per il punto più evidente: in PHP aggiungi questa riga alla sceneggiatura:header("Access-Control-Allow-Origin: *");
T30

1
@molto grazie MOLTO per la tua risposta. Mi hai aiutato molto. Saluti.
Luis Milanese,

10

È vero che la politica della stessa origine impedisce a JavaScript di effettuare richieste tra domini, ma la specifica CORS consente proprio il tipo di accesso API che stai cercando ed è supportata dal batch corrente dei principali browser.

Scopri come abilitare la condivisione delle risorse tra le origini per client e server:

http://enable-cors.org/

"La condivisione di risorse tra origini (CORS) è una specifica che consente un accesso veramente aperto oltre i confini del dominio. Se servi contenuti pubblici, considera l'utilizzo di CORS per aprirlo per l'accesso universale a JavaScript / browser."



9

Uso il server Apache, quindi ho usato il modulo mod_proxy. Abilita moduli:

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

Quindi aggiungere:

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

Infine, passa proxy-url al tuo script.




4

Dai documenti di Jquery ( link ):

  • A causa delle restrizioni di sicurezza del browser, la maggior parte delle richieste "Ajax" sono soggette alla stessa politica di origine; la richiesta non può recuperare correttamente i dati da un dominio, sottodominio o protocollo diverso.

  • Le richieste di script e JSONP non sono soggette alle stesse restrizioni della politica di origine.

Quindi riterrei necessario utilizzare jsonp per la richiesta. Ma non ho provato questo da solo.


2

Conosco 3 modi per risolvere il tuo problema:

  1. Innanzitutto se hai accesso a entrambi i domini puoi consentire l'accesso a tutti gli altri domini usando:

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

    o solo un dominio aggiungendo il codice seguente al file .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. puoi avere una richiesta Ajax a un file PHP nel tuo server e gestire la richiesta a un altro dominio usando questo file PHP.

  3. puoi usare jsonp, perché non necessita di autorizzazione. per questo puoi leggere la risposta del nostro amico @BGerrissen.

0

Per Microsoft Azure, è leggermente diverso.

Azure ha un'impostazione CORS speciale che deve essere configurata. È essenzialmente la stessa cosa dietro le quinte, ma semplicemente l'impostazione dell'intestazione menzionata da joshuarh non funzionerà. La documentazione di Azure per l'abilitazione del dominio incrociato è disponibile qui:

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

Mi sono occupato di questo per alcune ore prima di rendermi conto che la mia piattaforma di hosting aveva questa impostazione speciale.


0

funziona, tutto ciò che serve:

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 }
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.