IE9 jQuery AJAX với CORS trả về Truy cập bị từ chối


123

Các hoạt động sau đây trong tất cả các trình duyệt ngoại trừ IE (Tôi đang thử nghiệm trong 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'
            }
        );

Tôi có một chức năng khác sử dụng dataType: 'jsonp', nhưng tôi không cần bất kỳ dữ liệu nào được trả về trong cuộc gọi AJAX này. Phương án cuối cùng của tôi sẽ là trả lại một số jibberish được gói trong JSONP chỉ để làm cho nó hoạt động.

Bất kỳ ý tưởng tại sao IE đang vặn vẹo với một yêu cầu CORS không trả lại dữ liệu?


Vì không có câu trả lời nào được đề xuất cho tôi (tôi cũng phải chuyển cookie vào yêu cầu CORS, điều này là không nên khi sử dụng XDomainRequest), đây là một cách giải quyết: blog.gauffin.org/2014/04/ . Proxy để giải cứu! : p
wimvds

Câu trả lời:


150

Đây là một lỗi đã biết với jQuery. Nhóm jQuery "không có kế hoạch hỗ trợ điều này trong lõi và phù hợp hơn với vai trò là một plugin". (Xem bình luận này ). IE không sử dụng XMLHttpRequest , nhưng một đối tượng thay thế có tên XDomainRequest .

một plugin có sẵn để hỗ trợ này trong jQuery, mà có thể được tìm thấy ở đây : https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js

EDIT Chức năng $.ajaxTransportđăng ký một nhà máy vận chuyển. Một vận chuyển được sử dụng nội bộ bằng cách $.ajaxthực hiện các yêu cầu. Do đó, tôi cho rằng bạn sẽ có thể gọi $.ajaxnhư bình thường. Thông tin về vận chuyển và mở rộng $.ajaxcó thể được tìm thấy ở đây .

Ngoài ra, một phiên bản có lẽ tốt hơn của plugin này có thể được tìm thấy ở đây .

Hai lưu ý khác:

  1. Đối tượng XDomainRequest được giới thiệu từ IE8 và sẽ không hoạt động trong các phiên bản bên dưới.
  2. Từ IE10 CORS sẽ được hỗ trợ bằng cách sử dụng XMLHttpRequest bình thường .

Chỉnh sửa 2: vấn đề http sang https

Yêu cầu phải được nhắm mục tiêu đến cùng một sơ đồ như trang lưu trữ

Hạn chế này có nghĩa là nếu trang AJAX của bạn ở http://example.com , thì URL mục tiêu của bạn cũng phải bắt đầu bằng HTTP. Tương tự, nếu trang AJAX của bạn ở https://example.com , thì URL mục tiêu của bạn cũng phải bắt đầu bằng HTTPS.

Nguồn: http://bloss.msdn.com/b/ieiternals/archive/2010/05/13/xdomainrequest-restrictions-limemony-and-workaround.aspx


12
"Phiên bản tốt hơn" của plugin là bẩm sinh; Tôi chỉ đưa nó vào trang của mình và nó tự động sửa các cuộc gọi $ .ajax của tôi :) Tất nhiên, giả sử rằng bạn có tất cả các tiêu đề cần thiết .
Kato

5
Để thêm vào câu trả lời của dennisg, xdr.js có một lỗi - cuộc gọi lại ajaxTransport sẽ không được gọi như hiện tại. Tôi đã phải thay đổi nó theo stackoverflow.com/questions/12481560/ ((đã thêm "+ *" làm đối số đầu tiên của lệnh gọi ajaxTransport).
Volodymyr Otryshko

4
jQuery.XDomainRequest.js đảm bảo rằng trang hiện tại và trang từ xa đều là http hoặc https. Điều này có nghĩa là bạn không thể thực hiện cuộc gọi đến API https từ trang http?
Aaron

2
Điều đáng chú ý là mã được liên kết đến trên moonscripts github repo là một phiên bản cũ không hoạt động. Hãy chắc chắn để có được phiên bản mới nhất tại: raw.github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest/ mẹo
Clintm

3
@Aaron, thêm vào nhận xét của @ HariKaramSingh: thay đổi giao thức ( httpsang https), tên miền ( google.comsang bing.com), tên miền phụ ( mail.google.comsang maps.google.com) hoặc giao thức ( google.com:80- cổng mặc định google.com:8080) sẽ kích hoạt yêu cầu "tên miền chéo". Về cơ bản mọi thứ trước khi đầu tiên /trong URL của bạn cần phải giống hệt nhau.
allicarn

62

Xây dựng câu trả lời được chấp nhận bởi @dennisg, tôi đã thực hiện thành công điều này bằng cách sử dụng jQuery.XDomainRequest.js của MoonScript.

Đoạn mã sau hoạt động chính xác trong Chrome, Firefox và IE10, nhưng không thành công trong IE9. Tôi chỉ đơn giản bao gồm tập lệnh và bây giờ nó tự động hoạt động trong IE9. (Và có lẽ là 8, nhưng tôi chưa thử nó.)

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
Plugin jQuery.XDomainRequest.js chính xác là những gì tôi cần! Tôi không thể làm cho plugin iexhr.js hoạt động cho các yêu cầu đằng sau Xác thực cơ bản HTTP, nhưng XDomainRequest hoạt động như một cơ duyên!
James Ford

Điều này làm việc cho tôi. Tôi không cần Site.config (). ApiRoot + (mà tôi cho là dành cho twitter ....) Nhưng nó hoạt động rất tốt, cảm ơn vì đã làm điều này.
Nicholas Decker

@NicholasDecker Site.config (). ApiRoot chỉ là mã triển khai cụ thể để lấy URL gốc của API, không có gì phổ biến hay ưa thích. Vui vì nó đã giúp!
JackMorrissey

Tôi đã hy vọng điều này sẽ làm việc cho tôi, nhưng tôi đang cố gắng POST. tự hỏi nếu đó là vấn đề đối với tôi.
Jack Marchetti

1
@cracker Bạn chỉ gặp vấn đề với POST? Kiểm tra kỹ tập lệnh đang tải sau khi jQuery và cuộc gọi của bạn khớp với tài liệu của MoonScript.
JackMorrissey

16

Hướng dẫn đầy đủ về cách thực hiện việc này bằng cách sử dụng plugin "jQuery-ajaxTransport-XDomainRequest" tại đây: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest#in cản

Plugin này được hỗ trợ tích cực và xử lý HTML, JSON và XML. Tệp cũng được lưu trữ trên CDNJS, vì vậy bạn có thể trực tiếp thả tập lệnh vào trang của mình mà không cần thiết lập bổ sung: http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.1/jquery.xdomainrequest .min.js


1
Điều này làm việc tuyệt vời - thả trong sửa chữa. Không thể tin được rằng vấn đề này tồn tại trong jQuery nhưng ... Cảm ơn bạn!
Cymen

3

Vấn đề là IE9 trở xuống không hỗ trợ CORS. XDomainRequest chỉ hỗ trợ GET / POST và loại text/plainconten như được mô tả ở đây: http : //bloss.msdn.com/b/iei INTERNals / archive / 2010/05/13 / xdomainrequest-restrictions-limemony- and -workaround.aspx

Vì vậy, nếu bạn muốn sử dụng tất cả các động từ HTTP và / hoặc json, v.v., bạn phải sử dụng một giải pháp khác. Tôi đã viết một proxy sẽ hạ cấp xuống proxy một cách duyên dáng nếu IE9 trở xuống được sử dụng. Bạn hoàn toàn không phải thay đổi mã nếu bạn đang sử dụng ASP.NET.

Giải pháp là hai phần. Cái đầu tiên là một tập lệnh jquery nối vào quá trình xử lý ajax của jQuery. Nó sẽ tự động gọi máy chủ web nếu yêu cầu tên miền chéo được thực hiện và trình duyệt là 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;
    }
});

Trong máy chủ web của bạn, bạn phải nhận được yêu cầu, nhận giá trị từ tiêu đề http X-CorsProxy-Url và thực hiện yêu cầu HTTP và cuối cùng trả về kết quả.

Bài đăng trên blog của tôi: http://blog.gauffin.org/2014/04/how-to-use-cors-requests-in-iNET-explorer-9-and-below/


1

Tôi vừa thực hiện tất cả các yêu cầu JSONP vì đó là giải pháp duy nhất cho tất cả các trình duyệt được hỗ trợ của chúng tôi (IE7 + và các cơ quan quản lý). Nhắc bạn, câu trả lời của bạn về mặt kỹ thuật hoạt động cho IE9 để bạn có câu trả lời đúng.


2
Chỉ là một lưu ý cho bất kỳ ai có vấn đề này-- trong trường hợp này, nếu bạn có yêu cầu <= IE7 và bạn không có quyền kiểm soát máy chủ (ví dụ: không thể hỗ trợ thẻ GET + thẻ script w / JSONP) đặt cược tốt nhất là một máy chủ phần mềm trung gian nhẹ giúp chuyển cuộc gọi JSONP sang POST và truyền phản hồi từ máy chủ hộp đen trở lại cho người dùng.
mikermcneil



0

Để giải quyết vấn đề này, hãy kiểm tra xem bạn có một số .js được bao gồm trong tệp ajax của bạn có tên không: Tôi đã nhận được lỗi từ chối truy cập trong khi bao gồm Shadowbox.js trong ajax.php của tôi


0

Tôi đã thử nghiệm dịch vụ web CORS trên máy dev của mình và nhận được thông báo lỗi "Truy cập bị từ chối" chỉ trong IE. Firefox và Chrome hoạt động tốt. Hóa ra điều này là do tôi sử dụng localhost trong cuộc gọi ajax! Vì vậy, URL trình duyệt của tôi là một cái gì đó như:

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

và cuộc gọi ajax của tôi bên trong test.html là một cái gì đó như:

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

Mọi thứ hoạt động khi tôi thay đổi cuộc gọi ajax để sử dụng IP máy tính của mình thay vì localhost.

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

Cửa sổ "Mạng" của công cụ phát triển IE cũng hiển thị yêu cầu CORS Preflight theo sau bởi XMLHttpRequest GET, chính xác là những gì tôi dự kiến ​​sẽ thấy.




-1

Lưu ý - Lưu ý

không sử dụng " http://www.domain.xxx " hoặc " http: // localhost / " hoặc "IP >> 127.0.0.1" cho URL trong ajax. chỉ sử dụng đường dẫn (thư mục) và tên trang không có địa chỉ.

trạng thái sai:

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

trạng thái thực sự:

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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.