IE9 jQuery AJAX з CORS повертає "Доступ заборонено"


123

Далі працює у всіх браузерах, крім IE (я тестую в IE 9).

jQuery.support.cors = true;
...
        $.ajax(
            url + "messages/postMessageReadByPersonEmail",
            {
                crossDomain: true,
                data: {
                    messageId       : messageId,
                    personEmail     : personEmail
                },
                success: function() {
                    alert('marked as read');
                },
                error: function(a,b,c) {
                    alert('failed');
                },
                type: 'post'
            }
        );

У мене є ще одна функція, яка використовує dataType: 'jsonp', але мені не потрібні дані, повернені під час цього виклику AJAX. Моєю останньою інстанцією буде повернути трохи закрученого в JSONP просто для того, щоб воно працювало.

Будь-які ідеї, чому IE накручує запит CORS, який не повертає даних?


Оскільки жодна із запропонованих відповідей не працювала для мене (мені довелося також передавати файли cookie у запит CORS, що є "ні" при використанні XDomainRequest), ось вам: " blog.gauffin.org/2014/04/…" . Проксі на допомогу! : p
wimvds

Відповіді:


150

Це відома помилка з jQuery. Команда jQuery "не планує підтримувати це в ядрі і краще підходить як плагін". (Дивіться цей коментар ). IE не використовує XMLHttpRequest , а альтернативний об'єкт з назвою XDomainRequest .

Там є плагін для підтримки цього в JQuery, який можна знайти тут : https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js

EDIT Функція $.ajaxTransportреєструє завод-транспортер. Переносника використовується всередині по $.ajaxдля виконання запитів. Тому я припускаю, що ви повинні мати можливість телефонувати $.ajaxяк завжди. Інформацію про перевезення та розширення $.ajaxможна знайти тут .

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

Ще дві примітки:

  1. Об'єкт XDomainRequest був представлений з IE8 і не працюватиме у наведених нижче версіях.
  2. Від IE10 CORS буде підтримуватися за допомогою звичайного XMLHttpRequest .

Редагуйте 2: Проблема http для https

Запити повинні бути націлені на ту саму схему, що і хостинг-сторінка

Це обмеження означає, що якщо ваша сторінка AJAX знаходиться на веб-сайті http://example.com , то цільова URL-адреса також повинна починатися з HTTP. Так само, якщо ваша сторінка AJAX знаходиться на веб- сайті https://example.com , цільова URL-адреса також повинна починатися з HTTPS.

Джерело: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx


12
"Краща версія" плагіна є вродженою; Я просто включив його на свою сторінку, і він автоматично фіксував мої дзвінки $ .ajax :) Припустимо, звичайно, що у вас є всі необхідні заголовки .
Като

5
Щоб додати відповідь dennisg, у xdr.js є помилка - зворотний виклик ajaxTransport не буде викликаний так, як є. Мені довелося змінити його відповідно до stackoverflow.com/questions/12481560/… (додано "+ *" як перший аргумент виклику ajaxTransport).
Володимир Отришко

4
jQuery.XDomainRequest.js гарантує, що поточна та віддалена сторінка є або http, або https. Це означає, що ви не можете телефонувати на https API зі сторінки http?
Аарон

2
Варто зауважити, що код, з яким було пов’язано монографічні сценарії github repo, - це стара версія, яка не працює. Не забудьте отримати останню версію за адресою: raw.github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest/…
Clintm

3
@Aaron, додавши до коментаря @ HariKaramSingh: зміна протоколів ( httpдо https), доменів ( google.comдо bing.com), субдоменів ( mail.google.comдо maps.google.com) або протоколів ( google.com:80- порт за замовчуванням для google.com:8080) - все спричинить запит на "перехресний домен". В основному все перед першою /у вашій URL-адресі має бути ідентичним.
allicarn

62

Вибудовуючи прийняту відповідь від @dennisg, я досяг успіху за допомогою jQuery.XDomainRequest.js від MoonScript.

Наступний код справно працював у Chrome, Firefox та IE10, але не вдався до IE9. Я просто включив сценарій, і він тепер автоматично працює в IE9. (І, мабуть, 8, але я цього не перевіряв.)

var displayTweets = function () {
    $.ajax({
        cache: false,
        type: 'GET',
        crossDomain: true,
        url: Site.config().apiRoot + '/Api/GetTwitterFeed',
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        success: function (data) {
            for (var tweet in data) {
                displayTweet(data[tweet]);
            }
        }
    });
};

3
Плагін jQuery.XDomainRequest.js був саме тим, що мені потрібно! Я не зміг змусити плагін iexhr.js працювати для запитів, що стоять за базовою автентифікацією HTTP, але XDomainRequest працював як шарм!
Джеймс Форд

Це працювало для мене. Мені не знадобився Site.config (). ApiRoot + (який я припускаю, що це щебетати ....) Але він чудово працює, дякую за це.
Ніколас Декер

@NicholasDecker Site.config (). ApiRoot був просто конкретним кодом для реалізації, щоб отримати кореневу URL-адресу API, нічого універсального чи фантазійного. Рада, що це допомогло!
JackMorrissey

Я сподівався, що це буде працювати для мене, але я намагаюся розмістити. цікаво, чи це в мені проблема.
Джек Марчетті

1
@cracker У вас є лише проблеми з POST? Перевірте, чи завантажується сценарій після jQuery, і ваш дзвінок відповідає документації MoonScript.
JackMorrissey

16

Повні інструкції, як це зробити, використовуючи плагін "jQuery-ajaxTransport-XDomainRequest", можна знайти тут: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest#instructions

Цей плагін активно підтримується та обробляє HTML, JSON та XML. Цей файл також розміщений на CDNJS, тому ви можете безпосередньо перенести скрипт на свою сторінку без додаткових налаштувань: http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.1/jquery.xdomainrequest .min.js


1
Це спрацювало чудово - падіння виправлень. Неймовірно, що ця проблема існує у jQuery, але ... Дякую!
Цимен

3

Проблема полягає в тому, що IE9 і нижче не підтримують CORS. XDomainRequest підтримують лише GET / POST та text/plainтип вмісту, як описано тут: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

Отже, якщо ви хочете використовувати всі HTTP дієслова та / або json тощо, ви повинні використовувати інше рішення. Я написав проксі, який виграшно зменшить функцію проксі, якщо використовується IE9 або менше. Вам зовсім не потрібно змінювати код, якщо ви використовуєте ASP.NET.

Розчин складається з двох частин. Перший - це сценарій jquery, який підключається до обробки jQuery ajax. Він автоматично зателефонує веб-серверу, якщо буде зроблено запит crossDomain і браузер IE:

$.ajaxPrefilter(function (options, originalOptions, jqXhr) {
    if (!window.CorsProxyUrl) {
        window.CorsProxyUrl = '/corsproxy/';
    }
    // only proxy those requests
    // that are marked as crossDomain requests.
    if (!options.crossDomain) {
        return;
    }

    if (getIeVersion() && getIeVersion() < 10) {
        var url = options.url;
        options.beforeSend = function (request) {
            request.setRequestHeader("X-CorsProxy-Url", url);
        };
        options.url = window.CorsProxyUrl;
        options.crossDomain = false;
    }
});

На веб-сервері ви повинні отримати запит, отримати значення з заголовка X-CorsProxy-Url http і зробити HTTP-запит і нарешті повернути результат.

Мій пост у блозі: http://blog.gauffin.org/2014/04/how-to-use-cors-requests-in-internet-explorer-9-and-below/


1

Я просто зробив усі запити JSONP, оскільки це було єдиним рішенням для всіх підтримуваних нами браузерів (IE7 + та постійних). Зауважте, ваша відповідь технічно працює для IE9, щоб ви мали правильну відповідь.


2
Просто примітка для всіх, хто має цю проблему. У цьому випадку, якщо у вас є вимога <= IE7, і ви не маєте контролю над сервером (наприклад, не можу зробити так, щоб він підтримував теги GET + скриптів з JSONP) найкраща ставка - це легкий сервер середнього програмного забезпечення, який переводить дзвінок JSONP в POST і передає відповідь з сервера чорної скриньки назад до користувача.
mikermcneil

1

Спираючись на рішення MoonScript, ви можете спробувати це замість цього:

https://github.com/intuit/xhr-xdr-adapter/blob/master/src/xhr-xdr-adapter.js

Перевага полягає в тому, що оскільки це рішення нижчого рівня, воно дозволить CORS (наскільки це можливо) на IE 8/9 з іншими рамками, а не тільки з jQuery. Я мав успіх у використанні його з AngularJS, а також jQuery 1.x та 2.x.



0

Щоб вирішити цю проблему, також перевірте, чи включено у ваш файл ajax.


0

Я тестував веб-службу CORS на своїй машині розробки і отримував повідомлення про помилку "Доступ заборонено" лише в IE. Firefox та Chrome працювали чудово. Виявляється, це було викликано моїм використанням localhost у дзвінку в Аяксі! Тож моя URL-адреса браузера була приблизно такою:

http: //my_computer.my_domain.local/CORS_Service/test.html

і мій дзвінок Ajax всередині test.html був приблизно таким:

//fails in IE 
$.ajax({
  url: "http://localhost/CORS_Service/api/Controller",
  ...
});

Все працювало, як тільки я змінив дзвінок ajax, щоб використовувати IP свого комп'ютера замість localhost.

//Works in IE
$.ajax({
  url: "http://192.168.0.1/CORS_Service/api/Controller",
  ...
});

У вікні інструментів розробки IE на вкладці "Мережа" також відображається запит CORS Preflight OPTIONS, за яким слідує XMLHttpRequest GET, саме те, що я очікував побачити.


0

Оновлення станом на початок 2015 року. XDomain - це широко використовувана бібліотека для підтримки CORS на IE9 з обмеженим додатковим кодуванням.

https://github.com/jpillora/xdomain



-1

Примітка - Примітка

не використовуйте " http://www.domain.xxx " або " http: // localhost / " або "IP >> 127.0.0.1" для URL-адреси в ajax. використовувати лише шлях (каталог) та назву сторінки без адреси.

помилковий стан:

var AJAXobj = createAjax();
AJAXobj.onreadystatechange = handlesAJAXcheck;
AJAXobj.open('POST', 'http://www.example.com/dir/getSecurityCode.php', true);
AJAXobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
AJAXobj.send(pack);

справжній стан:

var AJAXobj = createAjax();
AJAXobj.onreadystatechange = handlesAJAXcheck;
AJAXobj.open('POST', 'dir/getSecurityCode.php', true);   // <<--- note
AJAXobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
AJAXobj.send(pack);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.