IE9 jQuery AJAX dengan CORS mengembalikan "Akses ditolak"

123

Berikut ini berfungsi di semua browser kecuali IE (saya sedang menguji di 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'
            }
        );

Saya memiliki fungsi lain yang digunakan dataType: 'jsonp', tetapi saya tidak memerlukan data apa pun yang dikembalikan pada panggilan AJAX ini. Pilihan terakhir saya adalah mengembalikan beberapa omong kosong yang dibungkus JSONP hanya untuk membuatnya berfungsi.

Adakah ide mengapa IE mengacaukan permintaan CORS yang tidak mengembalikan data?

Garrett
sumber
Karena tidak ada jawaban yang diusulkan yang berhasil untuk saya (saya juga harus memasukkan cookie ke permintaan CORS, yang merupakan no-no saat menggunakan XDomainRequest), berikut adalah solusinya : blog.gauffin.org/2014/04/… . Mewakili untuk menyelamatkan! : p
wimvds

Jawaban:

150

Ini adalah bug yang diketahui dengan jQuery. Tim jQuery "tidak memiliki rencana untuk mendukung ini secara inti dan lebih cocok sebagai plugin." (Lihat komentar ini ). IE tidak menggunakan XMLHttpRequest , tetapi objek alternatif bernama XDomainRequest .

Ada adalah sebuah plugin yang tersedia untuk mendukung ini di jQuery, yang dapat ditemukan di sini : https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js

EDIT Fungsi $.ajaxTransportmendaftarkan pabrik transporter. Transporter digunakan secara internal oleh $.ajaxuntuk melakukan permintaan. Oleh karena itu, saya menganggap Anda harus dapat menelepon $.ajaxseperti biasa. Informasi tentang pengangkut dan perluasan $.ajaxdapat ditemukan di sini .

Juga, versi yang mungkin lebih baik dari plugin ini dapat ditemukan di sini .

Dua catatan lainnya:

  1. Objek XDomainRequest diperkenalkan dari IE8 dan tidak akan berfungsi pada versi di bawah ini.
  2. Dari IE10 CORS akan didukung menggunakan XMLHttpRequest normal .

Edit 2: masalah http ke https

Permintaan harus ditargetkan ke skema yang sama seperti halaman hosting

Batasan ini berarti bahwa jika halaman AJAX Anda di http://example.com , maka URL target Anda juga harus dimulai dengan HTTP. Demikian pula, jika laman AJAX Anda di https://example.com , maka URL target Anda juga harus dimulai dengan HTTPS.

Sumber: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

dennisg
sumber
12
"Versi yang lebih baik" dari plugin adalah bawaan; Saya baru saja memasukkannya ke halaman saya dan secara otomatis memperbaiki panggilan $ .ajax saya :) Dengan asumsi, tentu saja, Anda memiliki semua header yang diperlukan .
Kato
5
Untuk menambah jawaban dennisg, xdr.js memiliki bug - callback ajaxTransport tidak akan dipanggil sebagaimana adanya. Saya harus mengubahnya sesuai dengan stackoverflow.com/questions/12481560/… (ditambahkan "+ *" sebagai argumen pertama panggilan ajaxTransport).
Volodymyr Otryshko
4
jQuery.XDomainRequest.js memastikan bahwa halaman saat ini dan halaman jarak jauh adalah http atau https. Apakah ini berarti Anda tidak dapat melakukan panggilan ke API https dari halaman http?
Aaron
2
Perlu dicatat bahwa kode yang ditautkan ke moonscripts github repo adalah versi lama yang tidak berfungsi. Pastikan untuk mendapatkan versi terbaru di: raw.github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest/…
Clintm
3
@Aaron, menambahkan komentar @HariKaramSingh: mengubah protokol ( httpke https), domain ( google.comke bing.com), subdomain ( mail.google.comke maps.google.com), atau protokol ( google.com:80- port default ke google.com:8080) semua akan memicu permintaan "lintas domain". Pada dasarnya segala sesuatu sebelum yang pertama /di URL Anda harus identik.
allicarn
62

Membangun jawaban yang diterima oleh @dennisg, saya menyelesaikan ini dengan sukses menggunakan jQuery.XDomainRequest.js oleh MoonScript.

Kode berikut bekerja dengan benar di Chrome, Firefox dan IE10, tetapi gagal di IE9. Saya hanya memasukkan skrip dan sekarang secara otomatis bekerja di IE9. (Dan mungkin 8, tapi saya belum mengujinya.)

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]);
            }
        }
    });
};
JackMorrissey
sumber
3
Plugin jQuery.XDomainRequest.js persis seperti yang saya butuhkan! Saya tidak bisa mendapatkan plugin iexhr.js bekerja untuk permintaan di belakang HTTP Basic Authentication, tetapi XDomainRequest bekerja dengan sangat baik!
James Ford
Ini berhasil untuk saya. Saya tidak membutuhkan Site.config (). ApiRoot + (yang saya asumsikan untuk twitter ....) Tapi berfungsi dengan baik, terima kasih telah melakukan ini.
Nicholas Decker
@NicholasDecker Site.config (). ApiRoot hanya mengimplementasikan kode khusus untuk mendapatkan URL root dari API, tidak ada yang universal atau mewah. Senang bisa membantu!
JackMorrissey
Saya berharap ini akan berhasil untuk saya, tetapi saya mencoba untuk POST. bertanya-tanya apakah itu masalah bagi saya.
Jack Marchetti
1
@ Cracker Apakah Anda hanya mengalami masalah dengan POST? Periksa kembali skrip dimuat setelah jQuery dan panggilan Anda cocok dengan dokumentasi MoonScript.
JackMorrissey
16

Petunjuk lengkap tentang cara melakukan ini menggunakan plugin "jQuery-ajaxTransport-XDomainRequest" dapat ditemukan di sini: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest#instructions

Plugin ini secara aktif didukung, dan menangani HTML, JSON dan XML. File ini juga dihosting di CDNJS, jadi Anda dapat langsung meletakkan skrip ke halaman Anda tanpa pengaturan tambahan: http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.1/jquery.xdomainrequest .min.js

MoonScript
sumber
1
Ini bekerja dengan baik - perbaikan penurunan. Sulit dipercaya bahwa masalah ini ada di jQuery tetapi ... Terima kasih!
Cymen
3

Masalahnya adalah IE9 dan versi di bawahnya tidak mendukung CORS. XDomainRequest hanya mendukung GET / POST dan text/plaintipe konten seperti yang dijelaskan di sini: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

Jadi jika Anda ingin menggunakan semua verba HTTP dan / atau json dll, Anda harus menggunakan solusi lain. Saya telah menulis proxy yang dengan anggun akan diturunkan ke proxy jika IE9 atau kurang digunakan. Anda tidak perlu mengubah kode sama sekali jika Anda menggunakan ASP.NET.

Solusinya ada dalam dua bagian. Yang pertama adalah skrip jquery yang menghubungkan ke pemrosesan ajax jQuery. Ini akan secara otomatis memanggil server web jika permintaan crossDomain dibuat dan browsernya adalah 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;
    }
});

Di server web Anda, Anda harus menerima permintaan tersebut, mendapatkan nilai dari header http X-CorsProxy-Url dan melakukan permintaan HTTP dan akhirnya mengembalikan hasilnya.

Entri blog saya: http://blog.gauffin.org/2014/04/how-to-use-cors-requests-in-internet-explorer-9-and-below/

jgauffin.dll
sumber
1

Saya baru saja membuat semua permintaan JSONP karena itu adalah satu-satunya solusi untuk semua browser yang kami dukung (IE7 + dan pelanggan tetap). Ingat, jawaban Anda secara teknis berfungsi untuk IE9 sehingga Anda memiliki jawaban yang benar.

Garrett
sumber
2
Hanya catatan untuk siapa pun dengan masalah ini-- dalam hal ini, jika Anda memiliki persyaratan <= IE7, dan Anda tidak memiliki kendali atas server (mis. Tidak dapat membuatnya mendukung GET + tag skrip dengan JSONP) Anda Taruhan terbaik adalah server middleware ringan yang menerjemahkan panggilan JSONP menjadi POST dan mengalirkan respons dari server kotak hitam kembali ke pengguna.
mikermcneil
1

Membangun solusi dengan MoonScript, Anda dapat mencoba ini sebagai gantinya:

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

Manfaatnya adalah karena ini adalah solusi tingkat yang lebih rendah, ini akan mengaktifkan CORS (sejauh mungkin) di IE 8/9 dengan kerangka kerja lain, tidak hanya dengan jQuery. Saya telah berhasil menggunakannya dengan AngularJS, serta jQuery 1.x dan 2.x.

yanni
sumber
0

Untuk mengatasi masalah ini, periksa juga apakah Anda memiliki beberapa yang disertakan .js ke dalam file ajax Anda yang disebut: Saya menerima kesalahan Akses ditolak saat menyertakan shadowbox.js di ajax.php saya

hacklover
sumber
0

Saya sedang menguji layanan web CORS pada mesin dev saya dan mendapatkan pesan kesalahan "Akses ditolak" hanya di IE. Firefox dan Chrome bekerja dengan baik. Ternyata ini disebabkan oleh penggunaan localhost saya di panggilan ajax! Jadi, URL browser saya seperti ini:

http: //komputer_saya.domain_saya.local/CORS_Service/test.html

dan panggilan ajax saya di dalam test.html adalah seperti:

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

Semuanya berfungsi setelah saya mengubah panggilan ajax untuk menggunakan IP komputer saya, bukan localhost.

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

Jendela alat pengembang IE "Jaringan" tab juga menampilkan permintaan OPSI Preflight CORS diikuti oleh XMLHttpRequest GET, yang persis seperti yang saya harapkan.

jwill212
sumber
0

Diperbarui pada awal 2015. xDomain adalah pustaka yang banyak digunakan untuk mendukung CORS di IE9 dengan pengkodean tambahan terbatas.

https://github.com/jpillora/xdomain

Bernard
sumber
-1

Catatan - Catatan

jangan gunakan " http://www.domain.xxx " atau " http: // localhost / " atau "IP >> 127.0.0.1" untuk URL di ajax. hanya gunakan jalur (direktori) dan nama halaman tanpa alamat.

keadaan salah:

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

keadaan sebenarnya:

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);
ali bagheri
sumber