IE9 jQuery AJAX mit CORS gibt "Zugriff verweigert" zurück.

123

Das Folgende funktioniert in allen Browsern außer IE (ich teste in 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'
            }
        );

Ich habe eine andere Funktion, die verwendet dataType: 'jsonp', aber ich brauche keine Daten, die bei diesem AJAX-Aufruf zurückgegeben werden. Mein letzter Ausweg wird sein, etwas in JSONP eingewickeltes Jibberish zurückzugeben, damit es funktioniert.

Irgendwelche Ideen, warum der IE eine CORS-Anfrage vermasselt, die keine Daten zurückgibt?

Garrett
quelle
Da keine der vorgeschlagenen Antworten für mich funktioniert hat (ich musste auch Cookies an die CORS-Anfrage übergeben, was bei Verwendung von XDomainRequest ein Nein-Nein ist), hier eine Problemumgehung : blog.gauffin.org/2014/04/… . Stellvertretend für die Rettung! : p
wimvds

Antworten:

150

Dies ist ein bekannter Fehler bei jQuery. Das jQuery-Team hat "keine Pläne, dies im Kern zu unterstützen und eignet sich besser als Plugin". (Siehe diesen Kommentar ). IE ist nicht die Verwendung von XMLHttpRequest , sondern ein alternativen Objekt namens XDomainRequest .

Es ist ein Plugin zur Verfügung dies in jQuery zu unterstützen, die hier gefunden werden kann : https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js

BEARBEITEN Die Funktion $.ajaxTransportregistriert eine Transporterfabrik. Ein Transporter verwendet intern durch $.ajaxAnfragen durchzuführen. Daher gehe ich davon aus , dass Sie $.ajaxwie gewohnt anrufen können sollten . Informationen zu Transportern und Erweiterungen $.ajaxfinden Sie hier .

Eine vielleicht bessere Version dieses Plugins finden Sie hier .

Zwei weitere Anmerkungen:

  1. Das Objekt XDomainRequest wurde von IE8 eingeführt und funktioniert in den folgenden Versionen nicht.
  2. Ab IE10 wird CORS mit einer normalen XMLHttpRequest unterstützt .

Bearbeiten 2: http zu https Problem

Anfragen müssen auf dasselbe Schema wie die Hosting-Seite ausgerichtet sein

Diese Einschränkung bedeutet, dass Ihre Ziel-URL auch mit HTTP beginnen muss , wenn sich Ihre AJAX-Seite unter http://example.com befindet. Wenn sich Ihre AJAX-Seite unter https://example.com befindet , muss Ihre Ziel-URL ebenfalls mit HTTPS beginnen.

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

dennisg
quelle
12
Die "bessere Version" des Plugins ist angeboren; Ich habe es gerade in meine Seite aufgenommen und meine $ .ajax-Aufrufe automatisch korrigiert :) Vorausgesetzt natürlich, Sie haben alle erforderlichen Header .
Kato
5
Xdr.js hat einen Fehler - ajaxTransport-Rückruf wird nicht so wie er ist aufgerufen. Ich musste es gemäß stackoverflow.com/questions/12481560/… ändern (als erstes Argument des AjaxTransport-Aufrufs wurde "+ *" hinzugefügt).
Volodymyr Otryshko
4
jQuery.XDomainRequest.js stellt sicher, dass die aktuelle Seite und die Remote-Seite entweder http oder https sind. Bedeutet dies, dass Sie eine https-API nicht von einer http-Seite aus aufrufen können?
Aaron
2
Es ist erwähnenswert, dass der Code, mit dem auf Moonscripts Github Repo verknüpft wurde, eine alte Version ist, die nicht funktioniert. Stellen
Clintm
3
@Aaron, der zu @ HariKaramSinghs Kommentar hinzugefügt wird: Das Ändern von Protokollen ( httpbis https), Domänen ( google.combis bing.com), Subdomänen ( mail.google.combis maps.google.com) oder Protokollen ( google.com:80- der Standardport bis google.com:8080) löst eine domänenübergreifende Anforderung aus. Grundsätzlich muss alles vor dem ersten /in Ihrer URL identisch sein.
Allicarn
62

Aufbauend auf der akzeptierten Antwort von @dennisg habe ich dies erfolgreich mit jQuery.XDomainRequest.js von MoonScript erreicht.

Der folgende Code funktionierte in Chrome, Firefox und IE10 ordnungsgemäß, schlug jedoch in IE9 fehl. Ich habe das Skript einfach eingefügt und es funktioniert jetzt automatisch in IE9. (Und wahrscheinlich 8, aber ich habe es nicht getestet.)

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
quelle
3
Das Plugin jQuery.XDomainRequest.js war genau das, was ich brauchte! Ich konnte das Plugin iexhr.js nicht für Anforderungen hinter der HTTP-Basisauthentifizierung verwenden, aber XDomainRequest funktionierte wie ein Zauber!
James Ford
Das hat bei mir funktioniert. Ich brauchte Site.config () nicht. ApiRoot + (was ich für Twitter annehme ...) Aber es funktioniert großartig, danke dafür.
Nicholas Decker
@NicholasDecker Site.config (). ApiRoot war nur implementierungsspezifischer Code, um die Root-URL der API zu erhalten, nichts Universelles oder Phantasievolles. Ich bin froh, dass es geholfen hat!
JackMorrissey
Ich hatte gehofft, dass dies für mich funktionieren würde, aber ich versuche zu POSTEN. Ich frage mich, ob das das Problem für mich ist.
Jack Marchetti
1
@cracker Haben Sie nur Probleme mit POST? Überprüfen Sie, ob das Skript nach jQuery geladen wird und Ihr Aufruf mit der Dokumentation von MoonScript übereinstimmt.
JackMorrissey
16

Vollständige Anweisungen dazu mit dem Plugin "jQuery-ajaxTransport-XDomainRequest" finden Sie hier: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest#instructions

Dieses Plugin wird aktiv unterstützt und verarbeitet HTML, JSON und XML. Die Datei wird auch auf CDNJS gehostet, sodass Sie das Skript ohne zusätzliche Einrichtung direkt auf Ihrer Seite ablegen können: http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.1/jquery.xdomainrequest .min.js

MoonScript
quelle
1
Das hat super geklappt - Drop in Fix. Unglaublich, dass dieses Problem in jQuery existiert, aber ... Danke!
Cymen
3

Das Problem ist, dass IE9 und niedriger CORS nicht unterstützen. XDomainRequest unterstützt nur GET / POST und den text/plainInhaltstyp, wie hier beschrieben: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

Wenn Sie also alle HTTP-Verben und / oder JSON usw. verwenden möchten, müssen Sie eine andere Lösung verwenden. Ich habe einen Proxy geschrieben, der ordnungsgemäß auf Proxy heruntergestuft wird, wenn IE9 oder weniger verwendet wird. Sie müssen Ihren Code überhaupt nicht ändern, wenn Sie ASP.NET verwenden.

Die Lösung besteht aus zwei Teilen. Das erste ist ein jquery-Skript, das sich in die jQuery-Ajax-Verarbeitung einfügt. Der Webserver wird automatisch aufgerufen, wenn eine CrossDomain-Anfrage gestellt wird und der Browser IE ist:

$.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;
    }
});

Auf Ihrem Webserver müssen Sie die Anforderung empfangen, den Wert aus dem X-CorsProxy-Url-HTTP-Header abrufen, eine HTTP-Anforderung ausführen und schließlich das Ergebnis zurückgeben.

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

jgauffin
quelle
1

Ich habe gerade alle Anfragen an JSONP gestellt, da dies die einzige Lösung für alle von uns unterstützten Browser (IE7 + und die regulären Browser) war. Wohlgemerkt, Ihre Antwort funktioniert technisch für IE9, sodass Sie die richtige Antwort haben.

Garrett
quelle
2
Nur ein Hinweis für alle, die dieses Problem haben - in diesem Fall, wenn Sie eine <= IE7-Anforderung haben und keine Kontrolle über den Server haben (z. B. kann er GET + -Skript-Tags mit JSONP nicht unterstützen) Die beste Wahl ist ein leichter Middleware-Server, der den JSONP-Aufruf in einen POST übersetzt und die Antwort vom Black-Box-Server zurück an den Benutzer überträgt.
Mikermcneil
1

Aufbauend auf der Lösung von MoonScript können Sie stattdessen Folgendes versuchen:

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

Der Vorteil ist, dass CORS (soweit möglich) auf IE 8/9 mit anderen Frameworks (nicht nur mit jQuery) aktiviert wird, da es sich um eine Lösung auf niedrigerer Ebene handelt. Ich hatte Erfolg mit AngularJS sowie mit jQuery 1.x und 2.x.

Yanni
quelle
0

Um dieses Problem zu lösen, überprüfen Sie auch, ob Sie einige .js in Ihre Ajax-Datei aufgenommen haben, die heißt: Ich habe den Fehler Zugriff verweigert erhalten, während ich shadowbox.js in meine ajax.php aufgenommen habe

Hacklover
quelle
0

Ich habe einen CORS-Webdienst auf meinem Entwicklungscomputer getestet und nur im IE die Fehlermeldung "Zugriff verweigert" erhalten. Firefox und Chrome haben gut funktioniert. Es stellt sich heraus, dass dies durch meine Verwendung von localhost im Ajax-Aufruf verursacht wurde! Meine Browser-URL war also ungefähr so:

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

und mein Ajax-Aufruf in test.html war ungefähr so:

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

Alles hat funktioniert, als ich den Ajax-Aufruf geändert habe, um meine Computer-IP anstelle von localhost zu verwenden.

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

Auf der Registerkarte "Netzwerk" des IE-Dev-Tools-Fensters wird auch die CORS Preflight OPTIONS-Anforderung angezeigt, gefolgt von XMLHttpRequest GET, genau das, was ich erwartet hatte.

jwill212
quelle
0

Update ab Anfang 2015. xDomain ist eine weit verbreitete Bibliothek zur Unterstützung von CORS auf IE9 mit begrenzter zusätzlicher Codierung.

https://github.com/jpillora/xdomain

Bernard
quelle
-1

Hinweis - Hinweis

Verwenden Sie nicht " http://www.domain.xxx " oder " http: // localhost / " oder "IP >> 127.0.0.1" für URL in Ajax. Verwenden Sie nur Pfad (Verzeichnis) und Seitennamen ohne Adresse.

falscher Zustand:

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

wahrer Zustand:

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
quelle