2010-08-02 19 views
7

Tutto funziona perfettamente in Firefox e Chrome, ma se non in IE8 (8.0.6001.18702)IE8 XSS/Jquery problema

Questo è il codice di prova (Jquery 1.4.2) (stesso problema con $ .post):

$(function() { 
    $.get("http://domain2.tld/some.php", {}, function(response) { 
     alert(response); 
    }); 
}); 

questo codice viene eseguito in domain1.tld e viene caricato da domain2.tld, in questo modo:

<script type="text/javascript" src="http://domain2.tld/test.js"></script> 

sto ottenendo un messaggio "autorizzazione negata" in IE8. Ho provato finora senza successo:

1) l'aggiunta di domain1.tld (codice PHP):

header("X-XSS-Protection: 0"); 

2) disattivando il filtro XSS nelle opzioni di IE8.

sto usando IE8 debugger e si vede l'errore in linea 5113:

xhr.open(type, s.url, s.async); 

Se invece di chiamare $ .get (domain2.tld ...), io chiamo $ .get (domain1. tld ...) non c'è errore, il che mi conferma che si tratta di un problema di "stessa politica di origine" dell'XSS.

La mia unica soluzione (penso) lo sta facendo attraverso un proxy (codice php) ma preferirei non farlo in quanto influisce sulle prestazioni.

Qualcuno sa di un'alternativa/soluzione a questo problema?

Nota: l'aggiornamento di IE8 non è un'opzione poiché voglio testarlo senza aggiornamenti.

Un problema molto simile al mio: http://forum.jquery.com/topic/jquery-ui-tabs-ie8-and-injecting-elements-into-dom

risposta

5

(vi consiglio di controllare la lista vi posto prima di questa risposta)

per facilitare il processo, ho preso il plugin CORS e modificato. Non dovrai modificare il tuo codice Jquery esistente se usi solo $ .get e $ .post. L'ho testato su IE8 e funziona come previsto. Per il resto dei browser utilizzeranno le normali chiamate JQuery. È anche possibile aggiungere questo codice su richiesta (con tag condizionali). Leggere i commenti iniziali per ulteriori informazioni. Spero che aiuta ...

Ecco il codice (salvarlo ad esempio come jquery.xdomain.js):

/* 
* XDR (non-XHR) extension functions for IE8+ 
* Based in CORS plugin (http://plugins.jquery.com/project/cors) 
* Modified by A.Lepe (www.alepe.com, Aug 2010) 
* 
* It supports calls using $.get and $.post only. 
* The main difference between the CORS plugin and this one are: 
* 
* 1) This method tries first to use XDR and if not available 
* will try to use XHR. This is to prevent any alert or 
* security message from IE. 
* 
* 2) To minimize size and target only IE8+ versions, this method 
* does not provides an alternative fall-back. 
* CORS version uses proxy_xmlhttp.js as fall-back option (see link #1 below). 
* 
* If you want to support "OLD" browsers, an alternative fall-back 
* can be easily implemented (instead the error alert). 
* For example, something like: 
* 
* ... 
* } catch(e) { 
* data["proxy_url"] = url; 
* $._get(proxy, data, callback, type); 
* } 
* ... 
* 
* in which "proxy" must be a URL where your proxy is located. 
* Your proxy may look like: 
* 
* <?php 
    //GET method example: 
    $URL = $_GET["proxy_url"]; 
    unset($_GET["proxy_url"]); 
    $params = http_build_query($_GET); 
    echo file_get_contents($URL."?".$params)); 
* ?> 
* 
* For POST method you may check link #2. 
* 
* NOTES: 
* 
* $.post() method it might not work as expected. XDR does 
* not send the data to the server in the same way XHR do 
* (am I missing something?). In order to have access to that 
* POST data you will need to: 
* 
* a) set: 
*  always_populate_raw_post_data = On 
*  register_long_arrays = On 
* 
* OR : 
* 
* b) import it manually (see link #3): 
    //-------- Import XDR POST data --------- 
    if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) { 
     $data = explode('&', $GLOBALS["HTTP_RAW_POST_DATA"]); 
     foreach ($data as $val) { 
      if (!empty($val)) { 
       list($key, $value) = explode('=', $val); 
       $_POST[$key] = urldecode($value); 
      } 
     } 
    } 
* 
* Remember to add the respective headers in the server that will 
* allow the XDR calls: 
     header('Access-Control-Allow-Origin: *'); //Or http://example.com 
     header('Access-Control-Max-Age: 3628800'); 
     header('Access-Control-Allow-Methods: GET, POST'); 
*/ 
(function($) { 
$._get = $.get; 
$._post = $.post; 
$.get = function (url, data, callback, type) { 
    // try XDR 
    if (jQuery.browser.msie && window.XDomainRequest) { 
     var params = ''; 
     for (var key in data) { 
      params += ((params || url.indexOf("?") != -1)?'&':'?')+key+'='+data[key]; 
     } 
     // Use Microsoft XDR 
     var xdr = new XDomainRequest(); 
     xdr.open("GET", url+params); 
     xdr.onload = function() { 
      callback(this.responseText, 'success'); 
     }; 
     xdr.send(); 
    } else { 
     try { 
      // Try using jQuery to get data 
      $._get(url, data, callback, type); 
     } catch(e) { 
      alert(e.message); 
     } 
    } 
} 
$.post = function (url, data, callback, type) { 
    // Try XDR 
    if (jQuery.browser.msie && window.XDomainRequest) { 
     var params = ''; 
     for (var key in data) { 
      params += (params?'&':'')+key+'='+data[key]; 
     } 
     // Use XDR 
     var xdr = new XDomainRequest(); 
     xdr.open("POST", url); 
     xdr.send(params); 
     xdr.onload = function() { 
      callback(xdr.responseText, 'success'); 
     }; 
    } else { 
     try { 
      // Try using jQuery to POST 
      $._post(url, data, callback, type); 
     } catch(e) { 
      alert(e.message); 
     } 
    } 
} 
})(jQuery); 

vicini:

+0

Grazie per questo! Tuttavia, nell'impiego recente di questo caso, ho scoperto che rompe leggermente la funzionalità nativa di '$ .get' e' $ .post', che restituiscono ciascun oggetto jqXHR. Questo è facilmente aggiustato modificando i blocchi try nel tuo codice per leggere 'return $ ._ get (url, data, callback, type);' e 'return $ ._ post (url, data, callback, type);' – itsmequinn

-1

Dovro 'essere d'accordo con JANDY qui, è molto improbabile you got it funziona affatto. Si applica lo stesso criterio di origine (http://en.wikipedia.org/wiki/Same_origin_policy), la soluzione migliore è scrivere un proxy locale su cui il proprio script esegue il polling e quindi consentire al proxy di effettuare le chiamate tra domini.

8

Mi dispiace se il mio inglese non è perfetto, come posso vedere che non ero abbastanza chiaro ... Una delle mie principali preoccupazioni si spiega con altra persona qui: http://http://forum.jquery.com/topic/cross-domain-ajax-and-ie

Quindi, quale alternativa esiste?

1) XDomainRequest

Personalmente penso che questo sia il modo migliore per attuare cross-site scripting in IE8 + (come viene supportato in modo nativo). L'unico problema è che è un modo solo Microsoft. Ma come molte altre cose con la famiglia IE possiamo facilmente estendere la funzionalità Ajax di JQuery.

In base alla documentazione, è necessario specificare alcune intestazioni aggiuntive nel dominio1.tld, for example, in PHP come questo:

header("Access-Control-Allow-Origin: http://domain2.tld"); //use * for any 

Forse la prossima alternativa è utile per fornire l'attuazione jquery di XDomainRequest;

Update (a): C'è un XDR library (non jquery), che "sostituire" la classe XHR per renderlo cross-browser, si basa in pmxdr client library. Non l'ho ancora provato.

2) CORS

L'unico problema con questo plugin è che non è esattamente un'estensione come le sue funzioni sono chiamati in modo diverso, quindi è necessario o modificare i codici o avvolgere quel plugin.

Aggiornamento (b): Ho modificato il plug-in CORS per renderlo più semplice. Controlla la mia altra risposta per ottenere il codice.

3) JsonP in JQuery

questo dovrebbe essere il modo più semplice per risolvere il mio problema (come ho il controllo di entrambi i server). Nativamente la maggior parte dei browser supporta lo scripting cross-site, solo se viene usato il formato JSON (credo che anche xml possa essere usato). In questo caso viene utilizzata la funzione $ .getJSON(). Per farlo funzionare, è necessario specificare (come afferma la documentazione) callback =? nell'URL, ad esempio:

$.getJSON("http://domain2.tld/index.php?callback=?",funciton(res){ ... }); 

Il "?" dopo "callback" sarà sostituito con un identificatore ... nel file php, è necessario per ottenere tale identificatore e circondano il codice JSON come questo:

print_r($_GET["callback"])."(".json_encode($mydata).");"; 

(che ho avuto ad esempio da here)

Il problema con questo metodo è che se si desidera recuperare solo HTML, deve risiedere all'interno di un oggetto json e quindi rendere il processo un po 'più complicato e travolgente.

4) jquery.jsonp plugin

Se avete bisogno di convalide e funzioni aggiuntive per il supporto nativo JSONP in jQuery, quindi provare questo plugin che sarà anche semplificare il processo.

5) xdomainajax

Questo plugin utilizza un aproach interessante utilizzando il servizio di Yahoo YQL, in cui qualsiasi pagina web (o una parte di esso) possono essere convertiti in JSON, rendendo possibile importarlo in javascript. Questo metodo è utile per quelle situazioni in cui non è possibile modificare il formato di origine.

6) flXHR

Questa soluzione utilizza Flash (SWF) per ottenere la magia. Potrei dire che questo è un modo molto veloce per ottenere un'implementazione quasi cross-browser (poiché si basa sul supporto flash). Questo metodo può essere l'ideale per quei siti in cui il flash sarà presente (di sicuro). Tuttavia, se il tuo sito non richiede flash, questo diventa il principale svantaggio dato che gli utenti devono avere installato Flash per funzionare.

7) xdajax

Questa soluzione si basa nell'attuazione YUI insieme con l'approccio "Flash".

8) Se nessuna delle opzioni precedenti è buona per te, ricorda che puoi ancora usare il vecchio trucco di inserire un tag per importare il codice JS.

9) Anche la riduzione della sicurezza IE al minimo risolve il problema. Ma penso che non sarebbe bello avere un messaggio del genere: "Si prega di abbassare le impostazioni di sicurezza per utilizzare questo sito" ... lol

Spero che questo possa aiutare gli altri in una situazione simile.

+0

Eccellente scrittura. –