JQuery AJAX кросс-домен

464

Вот две страницы: test.php и 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);
?>

Теперь моя проблема: когда оба этих файла находятся на одном сервере (локальном или веб-сервере), он работает и вызывается alert("Success"); Если он находится на разных серверах, то есть testerver.php на веб-сервере и test.php на localhost, его не работает и alert("Error") выполняется. Даже если URL-адрес внутри ajax изменен на http://domain.com/path/to/file/testserver.php

Теги:
cross-domain

15 ответов

375
Лучший ответ

Используйте 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).");";
?>

Эхо может быть неправильным, это было некоторое время, так как я использовал php. В любом случае вам нужно вывести callbackName('jsonString') заметить кавычки. jQuery передаст свое собственное имя обратного вызова, поэтому вам нужно получить это из параметров GET.

И, как писал Стефан Кендалл, $.getJSON() - это сокращенный метод, но тогда вам нужно добавить 'callback=?' к url как параметр GET (да, значение is?, jQuery заменяет его собственным методом обратного вызова).

  • 2
    Почему вам нужно возвращать callbackName('/* json */') вместо callbackName(/* json */) ?
  • 3
    @eric обратный вызов ожидает строку JSON. Теоретически, объект может также работать, но не уверен, как jQuery реагирует на это, он может выдать ошибку или потерпеть неудачу молча.
Показать ещё 9 комментариев
186

JSONP - хороший вариант, но есть более простой способ. Вы можете просто установить заголовок Access-Control-Allow-Origin на своем сервере. Установка его на * будет принимать междоменные запросы AJAX из любого домена. (https://developer.mozilla.org/en/http_access_control)

Метод для этого будет, разумеется, варьироваться от языка к языку. Здесь он находится в Rails:

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

В этом примере действие say_hello будет принимать запросы AJAX из любого домена и вернуть ответ "привет!".

Вот пример заголовков, которые он может вернуть:

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

Просто, как есть, у него есть некоторые ограничения браузера. См. http://caniuse.com/#feat=cors.

  • 12
    Jsonp не поддерживал пост, ставил и удалял. Ваше решение отлично работает.
  • 34
    в заголовке PHP («Access-Control-Allow-Origin: *»);
Показать ещё 8 комментариев
27

Вы можете управлять этим через HTTP-заголовок, добавив Access-Control-Allow-Origin. Установка его на * будет принимать междоменные запросы AJAX из любого домена.

Использование PHP действительно просто, просто добавьте следующую строку в script, к которой вы хотите получить доступ из своего домена:

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

Не забудьте включить модуль mod_headers в httpd.conf.

19

Вам нужно взглянуть на Одинаковая политика происхождения:

При вычислении одна и та же политика происхождения является важной концепцией безопасности для количество программ на стороне браузера языки, такие как JavaScript. политика разрешает выполнение скриптов страницы, происходящие с того же сайта для доступа к другим методам и свойства без конкретных ограничений, но препятствует доступу к большинство методов и свойств в страниц на разных сайтах.

Чтобы вы могли получать данные, это должно быть:

Тот же протокол и хост

Вам нужно реализовать JSONP, чтобы обойти это.

  • 0
    Могу ли я получить рабочий пример, используя jsonp ?
16

Мне пришлось загрузить веб-страницу с локального диска "file:///C:/test/htmlpage.html", вызвать url "http://localhost/getxml.php" и сделать это в браузерах IE8 + и Firefox12 + используйте jQuery v1.7.2 lib, чтобы свести к минимуму шаблонный код. После прочтения десятки статей, наконец, понял это. Вот мое резюме.

  • сервер script (.php,.jsp,...) должен возвращать заголовок ответа HTTP Access-Control-Allow-Origin: *
  • перед использованием jQuery ajax установите этот флаг в javascript: jQuery.support.cors = true;
  • вы можете установить флаг один раз или каждый раз перед использованием функции jQuery ajax
  • теперь я могу читать XML-документ в IE и Firefox. Другие браузеры я не тестировал.
  • Ответный документ может быть простым/текстовым, xml, json или чем-либо еще

Вот пример jQuery ajax-вызова с некоторыми отладочными sysouts.

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

Верно, что политика одного и того же происхождения предотвращает выполнение запросов JavaScript по всем доменам, но спецификация CORS позволяет использовать только тот вид доступа к API, который вам нужен, и поддерживается текущей группой основных браузеров.

Посмотрите, как включить совместное использование ресурсов между клиентом и сервером:

http://enable-cors.org/

"Совместное использование ресурсов (CORS) - это спецификация, которая позволяет по-настоящему открывать доступ через границы домена. Если вы обслуживаете общедоступный контент, рассмотрите возможность использования CORS, чтобы открыть его для универсального доступа к JavaScript/браузерам".

9

Я использую сервер Apache, поэтому я использовал модуль mod_proxy. Включить модули:

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

Затем добавьте:

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

Наконец, передайте прокси-url на ваш script.

9

Это возможно, но вам нужно использовать JSONP, а не JSON. Ссылка Стефана указала вам в правильном направлении. Страница jQuery AJAX содержит дополнительную информацию о JSONP.

У Remy Sharp есть подробный пример с использованием PHP.

  • 0
    Да, ссылка Стефана, сэр, я изучаю это .... Большое спасибо вам всем ...
8

Защита браузера предотвращает создание ajax-звонка со страницы, размещенной в одном домене, на страницу, размещенную в другом домене; это называется " политика одного и того же происхождения".

5

Существует несколько примеров использования JSONP, которые включают обработку ошибок.

Однако обратите внимание, что при использовании JSONP событие ошибки не запускается! Смотрите: http://api.jquery.com/jQuery.ajax/ или jQuery ajax-запрос с использованием jsonp-ошибки

4

Из документов Jquery (ссылка):

  • Из-за ограничений безопасности браузера большинство запросов "Ajax" подчиняются одной и той же политике происхождения; запрос не может успешно извлекать данные из другого домена, субдомена или протокола.

  • Script, а запросы JSONP не подпадают под одни и те же ограничения политики происхождения.

Поэтому я бы сказал, что вам нужно использовать jsonp для запроса. Но не пробовал это сам.

1

Я знаю 3 способа решить вашу проблему:

  1. Сначала, если у вас есть доступ к обоим доменам, вы можете разрешить доступ ко всем другим доменам, используя:

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

    или просто домен, добавив следующий код в файл.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. вы можете получить запрос ajax в php файл на своем сервере и обработать запрос в другом домене, используя этот php файл.

  3. вы можете использовать jsonp, потому что ему не требуется разрешение. для этого вы можете прочитать ответ нашего друга @BGerrissen.
0

он работает, все, что вам нужно:

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

Для Microsoft Azure это немного отличается.

Azure имеет специальную настройку CORS, которая должна быть установлена. Это по сути то же самое, что и за кулисами, но просто установка заголовка joshuarh упоминаний не будет работать. Документацию Azure для включения кросс-домена можно найти здесь:

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

Я поработал с этим в течение нескольких часов, прежде чем осознать, что моя хостинговая платформа имеет эту специальную настройку.

-3

Для запросов AJAX с перекрестным контуром используйте следующий плагин jQuery. https://github.com/jinujd/jQuery-Async-Form Он работает асинхронно, без перезагрузки. Это не AJAX, но в большинстве случаев он выполняет задачу

Ещё вопросы

Сообщество Overcoder
Наверх
Меню