2010-08-02 5 views
7

Tout fonctionne parfaitement dans Firefox et Chrome, mais sauf dans IE8 (8.0.6001.18702)IE8 XSS/Jquery problème

C'est le code de test (JQuery 1.4.2) (même problème avec .post $):

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

ce code est exécuté en domain1.tld et il est chargé de domain2.tld, de cette façon:

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

Je reçois une "autorisation refusée" message dans IE8. Je l'ai essayé jusqu'à présent sans succès:

1) ajouter à domain1.tld (code php):

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

2) de désactiver le filtre XSS dans les options IE8.

J'utilise débogueur IE8 et il montre l'erreur dans la ligne 5113:

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

Si au lieu d'appeler .get $ (domain2.tld ...), je l'appelle .get $ (domain1. tld ...) il n'y a pas d'erreur, ce qui me confirme qu'il s'agit d'un problème de "même origine" XSS.

Ma seule solution (je pense) est de le faire via un proxy (code php) mais je préférerais ne pas le faire car cela affecte la performance.

Est-ce que quelqu'un connaît une alternative/solution à ce problème?

Note: La mise à jour de IE8 n'est pas une option car je veux la tester sans mise à jour.

Un problème très semblable à la mienne: http://forum.jquery.com/topic/jquery-ui-tabs-ie8-and-injecting-elements-into-dom

Répondre

5

(Je recommande de vérifier la liste que je poste avant cette réponse)

Pour faciliter le processus, je pris le plugin CORS et modifia. Vous n'aurez pas besoin de modifier votre code Jquery existant si vous utilisez simplement $ .get et $ .post. Je l'ai testé dans IE8 et cela fonctionne comme prévu. Pour le reste des navigateurs utilisera les appels JQuery normales. Vous pouvez même ajouter ce code à la demande (avec des étiquettes conditionnelles). Lisez les commentaires initiaux pour plus d'informations. J'espère que cela aide ...

Voici le code (enregistrez par exemple comme 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); 

Liens:

+0

Merci pour ça! Cependant, en utilisant ceci pour un peu d'un cas de bordure récemment, j'ai découvert qu'il casse légèrement la fonctionnalité native de '$ .get' et' $ .post', qui renvoient chacun un objet jqXHR. Ceci est facilement corrigé en modifiant les blocs try dans votre code pour lire 'return $ ._ get (url, données, callback, type);' et 'return $ ._ post (url, data, callback, type);' – itsmequinn

-1

Je vais devoir être d'accord avec Jandy ici, il est très peu probable que vous l'avez obtenu fonctionne pas du tout. La même règle d'origine s'applique (http://en.wikipedia.org/wiki/Same_origin_policy), le mieux est d'écrire un proxy local que votre script interroge, puis de laisser le proxy effectuer les appels interdomaines.

8

Je suis désolé si mon anglais est pas parfait, comme je vois que je n'étais pas assez clair ... Un de mes principales préoccupations est expliquée par une autre personne ici: http://http://forum.jquery.com/topic/cross-domain-ajax-and-ie

Alors, quelle alternative existe?

1) XDomainRequest

Personnellement, je pense que c'est la meilleure façon de mettre en œuvre les scripts inter-site dans IE8 + (comme il est pris en charge en mode natif). Le seul problème est que c'est un moyen Microsoft uniquement. Mais comme beaucoup d'autres choses avec la famille IE, nous pouvons facilement étendre la fonctionnalité ajax JQuery. Selon la documentation, vous devrez spécifier certains en-têtes supplémentaires dans domain1.tld, for example, in PHP comme ceci:

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

Peut-être que la prochaine alternative est utile de prévoir la mise en œuvre de jquery de XDomainRequest;

Mise à jour (a): Il y a un XDR library (non jquery) qui "remplacer" la classe XHR pour le rendre multi-navigateur, il est basé à pmxdr client library. Je n'ai pas encore essayé.

2) CORS

Le seul problème avec ce plugin est qu'il est pas exactement une extension que ses fonctions sont nommés différemment, de sorte que vous devez soit modifier vos codes ou enveloppez ce plugin.

Mise à jour (b): J'ai modifié le plugin CORS pour le rendre plus facile. Vérifiez mon autre réponse pour obtenir le code.

3) JsonP in JQuery

Cela devrait être la meilleure façon de résoudre mon problème (comme je l'ai contrôle des deux serveurs). Nativement, la plupart des navigateurs prennent en charge les scripts inter-sites, uniquement si le format json est utilisé (je crois que xml peut également être utilisé). Dans ce cas, la fonction $ .getJSON() est utilisée. Pour le faire fonctionner, vous devez spécifier (comme l'indique la documentation) callback =? dans l'URL, par exemple:

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

Le "?" après « callback » sera remplacé par un identifiant ... dans votre fichier php, vous devez obtenir cet identifiant et entourer le code JSON comme ceci:

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

(je suis arrivé cet exemple de here)

Le problème avec cette méthode est que si vous voulez récupérer uniquement le HTML, il doit résider dans un objet json et rendre ainsi le processus un peu plus compliqué et écrasant.

4) jquery.jsonp plugin

Si vous avez besoin des fonctionnalités supplémentaires et des validations au support natif JSONP dans JQuery, essayez ce plugin qui simplifiera aussi le processus.

5) xdomainajax

Ce plugin utilise une aproche intéressante en utilisant le service de Yahoo YQL, dans lequel une page Web (ou une partie de celui-ci) peuvent être convertis en JSON, permettant d'importer dans javascript. Cette méthode est bonne pour les situations dans lesquelles vous ne pouvez pas modifier le format d'origine.

6) flXHR

Cette solution utilise le flash (swf) pour obtenir la magie. Je pourrais dire que c'est un moyen très rapide de réaliser une implémentation totalement cross-browser (car elle repose sur le support flash). Cette méthode peut être idéale pour les sites dans lesquels le flash sera présent (à coup sûr). Toutefois, si votre site ne nécessite pas de flash, alors cela devient le principal inconvénient que les utilisateurs devraient avoir flash installé pour que cela fonctionne.

7) xdajax

Cette solution est basée sur la mise en œuvre de YUI ainsi que l'approche "Flash". 8) Si aucune des options précédentes ne vous convient, rappelez-vous que vous pouvez toujours utiliser l'ancienne astuce de l'insertion d'une balise pour importer du code JS.

9) Réduire au minimum la sécurité d'IE pour résoudre le problème. Mais je pense qu'il ne sera pas bon d'avoir un message comme celui-ci: "Veuillez baisser vos paramètres de sécurité pour utiliser ce site" ... lol

J'espère que cela peut aider les autres dans une situation similaire.

+0

Excellent article. –