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


477

Ось дві сторінки, 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")викликається; Якщо він знаходиться на різних серверах, тобто testserver.php на веб-сервері та test.php на localhost, він не працює, і alert("Error")виконується. Навіть якщо URL-адресу всередині ajax буде змінено на http://domain.com/path/to/file/testserver.php


38
Для людей, що зупиняються. Прочитайте це, щоб мати уявлення про те, як працюють міжвибійні
Abdul Munim

1
Відповідь на це питання я написав тут: Завантаження html-сторінки крос-домену з jQuery AJAX - останньою, підтримує https
jherax

Відповіді:


412

Використовуйте 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 (так, значення ?, jQuery замінює це власним створеним методом зворотного виклику).


2
Чому потрібно повертатися callbackName('/* json */')замість callbackName(/* json */)?
Ерік

3
@eric зворотний виклик очікує рядок JSON. Теоретично об’єкт може також працювати, але не впевнений, як jQuery реагує на це, він може призвести до помилки або мовчати.
BGerrissen

Я отримую таку помилку. SyntaxError: відсутній; перед оператором {"ResultCode": 2}. Де {"ResultCode": 2} - відповідь. Будь ласка, порадь.
користувач2003356

@ user2003356 виглядає так, що ви повертаєте звичайний JSON замість JSONP. Вам потрібно повернути щось на кшталт: callbackFunction ({"ResultCode": 2}). jQuery додає до запиту параметр GET 'зворотний виклик', це ім'я функції зворотного виклику, яке використовує jquery, і його слід додати до відповіді.
BGerrissen

2
Це 2016. CORS зараз широко підтримується стандарт, на відміну від JSONP, який можна охарактеризувати лише як злом. @ joshuarh відповідь нижче повинна бути кращою зараз.
Vicky Chijwani

202

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

Звичайно, спосіб цього буде відрізнятися від мови до мови. Ось це в Рейки:

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 не підтримував публікацію, ставити та видаляти. Ваше рішення чудово працює.
TonyTakeshi

35
у заголовку PHP ("Access-Control-Allow-Origin: *");
SparK

9
@Warrior Якщо ви використовуєте .post()метод jQuery, увімкніть підтримку між доменними в jQuery. Це робиться з цим: $.support.cors = true.
Friederike

21
Які наслідки безпеки для налаштування сервера таким чином?
Джон Шнайдер

19
Було б дозволити дозволити використовувати лише ті домени, з якими ви хочете поділитися даними, замість того, щоб використовувати wilcard "*".
Себастьян Гріньолі

32

Це можна керувати за допомогою заголовка HTTP, додавши Access-Control-Allow-Origin . Якщо встановити його *, буде прийнято міждоменні запити AJAX з будь-якого домену.

Використовуючи PHP дуже просто, просто додайте наступний рядок у сценарій, до якого ви хочете отримати доступ із вашого домену:

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

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


ти врятував мій день.
NomanJaved

20

Потрібно ознайомитись із політикою щодо самого оригіналу :

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

Щоб ви могли отримати дані, це повинні бути:

Той самий протокол і хост

Вам потрібно реалізувати JSONP, щоб вирішити його.


17

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

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

Ось приклад виклику jQuery ajax з деякими системою налагодження.

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
Відповідь на це запитання я написав тут: Завантаження html-сторінки крос-домену з jQuery AJAX - останньою, підтримує https
jherax

Для точки пожежі: в PHP додайте цей рядок до сценарію:header("Access-Control-Allow-Origin: *");
T30,

1
@whome дякую ДУЖЕ дуже за вашу відповідь. Ти мені дуже допоміг. Ура.
Луїс

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 до свого сценарію.




4

З документів Jquery ( посилання ):

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

  • На запити сценарію та JSONP не застосовуються однакові обмеження щодо політики походження.

Тому я вважаю, що вам потрібно використовувати jsonp для запиту. Але я сам не пробував цього.


2

Я знаю 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

Для Microsoft Azure - це дещо інакше.

Azure має спеціальне налаштування CORS, яке потрібно встановити. Це по суті те ж саме за кадром, але просто встановити заголовок, який згадує Джошуарх, не вийде. Документацію Azure для включення міждоменного сайту можна знайти тут:

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

Я декілька годин поспілкувався з цим, перш ніж зрозумів, що моя хостингова платформа мала ці особливі налаштування.


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 }
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.