关于Internet Explorer 9:带有CORS的IE9 jQuery AJAX返回“访问被拒绝”

IE9 jQuery AJAX with CORS returns “Access is denied”

除了IE(我在IE9中测试),以下所有浏览器都可以使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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的Jibberish,让它工作。

你知道为什么IE搞砸了一个没有返回数据的CORS请求吗?


这是jquery的已知错误。jquery团队"没有计划在核心中支持这一点,并且更适合作为插件。"(请参阅此注释)。IE不使用xmlhttpRequest,而是使用名为xdomainRequest的替代对象。

jquery中有一个插件可以支持这个功能,可以在这里找到:https://github.com/jaubourg/ajaxhooks/blob/master/src/xdr.js网站

编辑函数$.ajaxTransport注册运输工厂。$.ajax在内部使用转运体来执行请求。因此,我想你应该可以像往常一样给$.ajax打电话。关于转运体和扩展$.ajax的信息可以在这里找到。

此外,可以在这里找到这个插件的更好版本。

另外两个注意事项:

  • 对象xdomainRequest是从IE8引入的,在下面的版本中不起作用。
  • 使用普通的xmlhttpRequest将支持来自IE10的CORS。
  • 编辑2:HTTP到HTTPS问题

    Requests must be targeted to the same scheme as the hosting page

    This restriction means that if your AJAX page is at
    http://example.com, then your target URL must also begin with HTTP.
    Similarly, if your AJAX page is at https://example.com, then your
    target URL must also begin with HTTPS.

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


    基于@dennisg接受的答案,我使用moonscript的jquery.xdomainrequest.js成功地完成了这项工作。

    以下代码在Chrome、Firefox和IE10中工作正常,但在IE9中失败。我只是简单地包含了脚本,现在它在IE9中自动工作。(大概8个,但我还没有测试过。)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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]);
                }
            }
        });
    };


    有关如何使用"jquery ajaxtransport xdomainRequest"插件执行此操作的完整说明,请参见:https://github.com/moonscript/jquery-ajaxtransport-xdomainRequest说明

    这个插件被积极支持,并处理HTML、JSON和XML。该文件也宿主在cdnjs上,因此您可以直接将脚本放到页面中,而无需其他设置:http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.1/jquery.xdomainrequest.min.js


    问题是IE9及以下版本不支持CORS。xdomainRequest只支持get/post和text/plainconten类型,如下所述:http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainRequest-restrictions-limitations-and-workarounds.aspx

    因此,如果您想使用所有HTTP动词和/或JSON等,就必须使用另一种解决方案。我已经写了一个代理,如果使用IE9或更低,它将优雅地降级为代理。如果使用的是ASP.NET,则根本不需要更改代码。

    解决方案分为两部分。第一个脚本是jquery脚本,它钩住jquery ajax处理。如果提出跨域请求并且浏览器是IE,它将自动调用Web服务器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    $.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;
        }
    });

    在您的Web服务器中,您必须接收请求,从x-corsproxy-url HTTP头获取值,然后执行HTTP请求,最后返回结果。

    我的博客帖子:http://blog.gauffin.org/2014/04/how-to-use-cors-requests-in-internet-explorer-9-及以下/


    基于moonscript的解决方案,您可以尝试以下方法:

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

    好处是,由于它是一个较低级别的解决方案,它将在IE8/9上启用CORS(在可能的范围内)和其他框架,而不仅仅是JQuery。我已经成功地将它与AngularJS以及jQuery1.x和2.x一起使用。


    在Internet Explorer 8和更新版本中使用jquery获取跨域JSON

    非常有用的链接:

    http://graphicmaniacs.com/note/getting-a-cross-domain-json-with-jquery-in-internet-explorer-8-及更高版本/

    可以帮助解决从X域请求返回JSON的问题。

    希望这能帮助别人。


    我刚提出了所有的请求jsonp,因为它是我们所有支持的浏览器(IE7+和Regulars)的唯一解决方案。注意,你的答案在技术上适用于IE9,所以你有正确的答案。


    尝试对IE8/9中的CORS请求使用jquery transport xdr jquery插件。


    2015年初更新。xdomain是一个广泛使用的库,它支持IE9上的CORS,并且具有有限的额外编码。

    https://github.com/jpillora/xdomain


    我在我的开发人员机器上测试了一个CORS Web服务,并且只在IE中获得了"访问被拒绝"的错误消息。Firefox和Chrome工作正常。结果发现这是我在Ajax调用中使用localhost造成的!所以我的浏览器URL类似于:

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

    我对test.html内部的Ajax调用是这样的:

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

    一旦我更改了Ajax调用以使用我的计算机IP而不是本地主机,一切都会正常工作。

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

    ie dev工具窗口"network"选项卡还显示了cors preflight options请求,后面是xmlhttprequest get,这正是我期望看到的。


    要解决此问题,还需要检查Ajax文件中是否包含一些.js,这些文件名为:在Ajax.php中包含shadowbox.js时,收到拒绝访问错误。


    注释-注释

    不要将"http://www.domain.xxx"或"http://localhost/"或"ip>>127.0.0.1"用于Ajax中的URL。只使用没有地址的路径(目录)和页面名称。

    假状态:

    1
    2
    3
    4
    5
    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);

    真实状态:

    1
    2
    3
    4
    5
    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);