IE9 jQuery AJAX con CORS restituisce "Accesso negato"


123

Quanto segue funziona in tutti i browser tranne IE (sto provando 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'
            }
        );

Ho un'altra funzione che utilizza dataType: 'jsonp', ma non ho bisogno di alcun dato restituito su questa chiamata AJAX. La mia ultima risorsa sarà restituire un po 'di jibberish avvolto in JSONP solo per farlo funzionare.

Qualche idea sul perché IE sta rovinando una richiesta CORS che non restituisce dati?


Dal momento che nessuna delle risposte proposte ha funzionato per me (ho dovuto passare i cookie anche nella richiesta CORS, che è un no-no quando si utilizza XDomainRequest), ecco una soluzione: blog.gauffin.org/2014/04/… . Proxying in soccorso! : p
wimvds

Risposte:


150

Questo è un bug noto con jQuery. Il team di jQuery "non ha intenzione di supportarlo nel core ed è più adatto come plugin". (Vedi questo commento ). IE non utilizza XMLHttpRequest , ma un oggetto alternativo denominato XDomainRequest .

È disponibile un plug-in per supportarlo in jQuery, che può essere trovato qui : https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js

EDIT La funzione $.ajaxTransportregistra una fabbrica di trasportatori. Un trasportatore viene utilizzato internamente da $.ajaxper eseguire le richieste. Pertanto, presumo che dovresti essere in grado di chiamare $.ajaxcome al solito. Informazioni sui trasportatori e l'estensione $.ajaxpossono essere trovate qui .

Inoltre, una versione forse migliore di questo plugin può essere trovata qui .

Altre due note:

  1. L'oggetto XDomainRequest è stato introdotto da IE8 e non funzionerà nelle versioni seguenti.
  2. Da IE10 CORS sarà supportato utilizzando un normale XMLHttpRequest .

Modifica 2: problema da http a https

Le richieste devono essere indirizzate allo stesso schema della pagina di hosting

Questa restrizione significa che se la tua pagina AJAX è all'indirizzo http://example.com , anche l'URL di destinazione deve iniziare con HTTP. Allo stesso modo, se la tua pagina AJAX è su https://example.com , anche l'URL di destinazione deve iniziare con HTTPS.

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


12
La "versione migliore" del plugin è innata; L'ho appena incluso nella mia pagina e ha risolto automaticamente le mie chiamate $ .ajax :) Supponendo, ovviamente, che tu abbia tutte le intestazioni necessarie a posto.
Kato

5
Da aggiungere alla risposta dennisg, xdr.js ha un bug: la richiamata ajaxTransport non verrà chiamata così com'è. Ho dovuto cambiarlo in conformità con stackoverflow.com/questions/12481560/… (aggiunto "+ *" come primo argomento della chiamata ajaxTransport).
Volodymyr Otryshko

4
jQuery.XDomainRequest.js si assicura che la pagina corrente e la pagina remota siano entrambe http o https. Ciò significa che non è possibile effettuare una chiamata a un'API https da una pagina http?
Aaron

2
Vale la pena notare che il codice a cui era collegato il repository github moonscripts è una vecchia versione che non funziona. Assicurati di scaricare
Clintm

3
@Aaron, aggiungendo al commento di @ HariKaramSingh: la modifica di protocolli ( httpa https), domini ( google.coma bing.com), sottodomini ( mail.google.coma maps.google.com) o protocolli ( google.com:80- la porta predefinita a google.com:8080) attiverà tutti una richiesta "interdominio". Fondamentalmente tutto prima del primo /nel tuo URL deve essere identico.
allicarn

62

Partendo dalla risposta accettata da @dennisg, l'ho ottenuto con successo utilizzando jQuery.XDomainRequest.js di MoonScript.

Il codice seguente ha funzionato correttamente in Chrome, Firefox e IE10, ma non è riuscito in IE9. Ho semplicemente incluso lo script e ora funziona automaticamente in IE9. (E probabilmente 8, ma non l'ho testato.)

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
Il plugin jQuery.XDomainRequest.js era esattamente quello di cui avevo bisogno! Non sono riuscito a far funzionare il plugin iexhr.js per le richieste dietro l'autenticazione di base HTTP, ma XDomainRequest ha funzionato a meraviglia!
James Ford

Questo ha funzionato per me. Non avevo bisogno di Site.config (). ApiRoot + (che presumo sia per twitter ....) Ma funziona benissimo, grazie per averlo fatto.
Nicholas Decker

@NicholasDecker Site.config (). ApiRoot era solo un codice specifico per l'implementazione per ottenere l'URL radice dell'API, niente di universale o di fantasia. Sono contento che abbia aiutato!
JackMorrissey

Speravo che funzionasse per me, ma sto cercando di POST. mi chiedo se questo sia il problema per me.
Jack Marchetti

1
@cracker Hai solo problemi con il POST? Controlla che lo script si stia caricando dopo jQuery e che la tua chiamata corrisponda alla documentazione di MoonScript.
JackMorrissey

16

Le istruzioni complete su come eseguire questa operazione utilizzando il plug-in "jQuery-ajaxTransport-XDomainRequest" sono disponibili qui: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest#instructions

Questo plugin è attivamente supportato e gestisce HTML, JSON e XML. Il file è anche ospitato su CDNJS, quindi puoi inserire direttamente lo script nella tua pagina senza ulteriori configurazioni: http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.1/jquery.xdomainrequest .min.js


1
Ha funzionato alla grande - correzione rapida. Incredibile che questo problema esista in jQuery ma ... Grazie!
Cymen

3

Il problema è che IE9 e versioni precedenti non supportano CORS. XDomainRequest supporta solo GET / POST e il text/plaintipo di contenuto come descritto qui: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

Quindi, se vuoi usare tutti i verbi HTTP e / o json ecc. Devi usare un'altra soluzione. Ho scritto un proxy che eseguirà il downgrade con grazia al proxy se viene utilizzato IE9 o meno. Non è necessario modificare affatto il codice se si utilizza ASP.NET.

La soluzione è in due parti. Il primo è uno script jquery che si aggancia all'elaborazione jQuery ajax. Chiamerà automaticamente il server web se viene effettuata una richiesta crossDomain e il browser è 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;
    }
});

Nel tuo server web devi ricevere la richiesta, ottenere il valore dall'intestazione http di X-CorsProxy-Url ed eseguire una richiesta HTTP e infine restituire il risultato.

Il mio post sul blog: http://blog.gauffin.org/2014/04/how-to-use-cors-requests-in-internet-explorer-9-and-below/


1

Ho appena effettuato tutte le richieste JSONP perché era l'unica soluzione per tutti i nostri browser supportati (IE7 + e i clienti abituali). Intendiamoci, la tua risposta tecnicamente funziona per IE9 quindi hai la risposta corretta.


2
Solo una nota per chiunque abbia questo problema: in questo caso, se hai un requisito <= IE7 e non hai il controllo sul server (ad es. Non puoi farlo supportare GET + tag script w / JSONP) il tuo la cosa migliore è un server middleware leggero che traduce la chiamata JSONP in un POST e trasmette la risposta dal server black box all'utente.
mikermcneil



0

Per risolvere questo problema, controlla anche se hai alcuni .js inclusi nel tuo file ajax chiamato: Ho ricevuto l'errore di accesso negato includendo shadowbox.js nel mio ajax.php


0

Stavo testando un servizio web CORS sulla mia macchina di sviluppo e ricevevo il messaggio di errore "Accesso negato" solo in IE. Firefox e Chrome hanno funzionato bene. Si scopre che questo è stato causato dal mio uso di localhost nella chiamata ajax! Quindi l'URL del mio browser era qualcosa del tipo:

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

e la mia chiamata ajax all'interno di test.html era qualcosa del tipo:

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

Tutto ha funzionato una volta che ho cambiato la chiamata ajax per utilizzare l'IP del mio computer invece di localhost.

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

La scheda "Rete" della finestra degli strumenti di sviluppo di IE mostra anche la richiesta CORS Preflight OPTIONS seguita da XMLHttpRequest GET, che è esattamente quello che mi aspettavo di vedere.




-1

Nota - Nota

non utilizzare " http://www.domain.xxx " o " http: // localhost / " o "IP >> 127.0.0.1" per l'URL in ajax. utilizzare solo percorso (directory) e nome della pagina senza indirizzo.

stato falso:

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

stato vero:

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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.