2010-08-02 1 views
7

Todo funciona perfecto en Firefox y Chrome, pero excepto en IE8 (8.0.6001.18702)IE8 XSS/Jquery problema

Este es el código de prueba (jQuery 1.4.2) (mismo problema con $ .post):

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

este código se ejecuta en domain1.tld y se carga desde domain2.tld, de esta manera:

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

me estoy poniendo un "permiso denegado" en IE8. He tratado hasta ahora sin éxito:

1) añadir en domain1.tld (código php):

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

2) la desactivación del filtro XSS en IE8 opciones.

estoy usando IE8 depurador y se nota el error en la línea 5113:

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

Si en lugar de llamar $ .get (domain2.tld ...), que llamo $ .get (domain1. tld ...) no hay ningún error, lo que me confirma que se trata de un problema de "política de origen" de XSS.

Mi única solución (creo) es hacerlo a través de un proxy (código php), pero preferiría no hacerlo, ya que afecta el rendimiento.

¿Alguien sabe de una alternativa/solución a este problema?

Nota: La actualización de IE8 no es una opción, ya que quiero probarlo sin actualizaciones.

Un problema muy similar a la mía: http://forum.jquery.com/topic/jquery-ui-tabs-ie8-and-injecting-elements-into-dom

Respuesta

5

(recomiendo revisar la lista de correos antes de que esta respuesta)

Para facilitar el proceso, tomé el plugin CORS y lo modificó. No necesitará modificar su código Jquery existente si solo usa $ .get y $ .post. Lo probé en IE8 y funciona como se esperaba. Para el resto de los navegadores utilizará las llamadas JQuery normales. Incluso puede agregar este código a pedido (con etiquetas condicionales). Lea los comentarios iniciales para obtener más información. Espero que ayude ...

Aquí está el código (salvo que por ejemplo como 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); 

Enlaces:

+0

¡Gracias por esto! Sin embargo, al usar esto recientemente para un caso marginal, descubrí que rompe ligeramente la funcionalidad nativa de '$ .get' y' $ .post', que cada uno devuelve un objeto jqXHR. Esto se soluciona fácilmente modificando los bloques try en su código para leer 'return $ ._ get (url, data, callback, type);' y 'return $ ._ post (url, data, callback, type);' – itsmequinn

-1

Voy a tener que estar de acuerdo con Jandy aquí, es muy poco probable que lo tienes trabajando en absoluto. Se aplica la misma política de origen (http://en.wikipedia.org/wiki/Same_origin_policy), su mejor opción es escribir un proxy local que su secuencia de comandos sondee, y luego permita que el proxy haga las llamadas entre dominios.

8

Lo siento si mi Inglés no es perfecto, ya que puedo ver que no era lo suficientemente claro ... Una de mis principales preocupaciones se explica por otra persona aquí: http://http://forum.jquery.com/topic/cross-domain-ajax-and-ie

Entonces, ¿qué alternativa existe?

1) XDomainRequest

personalmente creo que esta es la mejor manera de implementar secuencias de comandos entre sitios en IE8 + (ya que es compatible de forma nativa). El único problema es que es una forma única de Microsoft. Pero como muchas otras cosas con la familia IE, podemos extender fácilmente la funcionalidad JQuery ajax.

De acuerdo con la documentación, deberá especificar algunos encabezados adicionales en domain1.TLD, for example, in PHP así:

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

Tal vez la siguiente alternativa es útil para proporcionar la aplicación de jQuery XDomainRequest;

Update (a): Hay una (no jQuery), que "reemplazar" la clase XHR para que sea multi-navegador XDR library, se basa en pmxdr client library. No lo he intentado todavía

2) CORS

El único problema con este plugin es que no es exactamente una extensión ya que sus funciones se nombran de manera diferente, por lo que necesita ya sea cambiar sus códigos o una envoltura de ese plugin.

Actualización (b): Modifiqué el complemento CORS para que sea más fácil. Verifique mi otra respuesta para obtener el código.

3) JsonP in JQuery

Esta debe ser la forma más fácil de resolver mi problema (ya que tengo el control de ambos servidores). Nativamente, la mayoría de los navegadores admiten scripts de sitios cruzados, solo si se utiliza el formato json (creo que también se puede usar xml). En este caso, se usa la función $ .getJSON(). Para que funcione, debe especificar (como lo indica la documentación) callback =? en la URL, por ejemplo:

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

¿El "?" después de "devolución de llamada" será reemplazado con un identificador ... en su archivo PHP, es necesario conseguir que el identificador y rodear el código JSON como esto:

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

(Tengo ese ejemplo de here)

El problema con este método es que si solo desea recuperar HTML, debe residir dentro de un objeto json y hacer que el proceso sea un poco más complicado y abrumador.

4) jquery.jsonp plugin

Si necesita validaciones y características adicionales para el apoyo JSONP nativo en jQuery, y luego tratar este plugin que también simplificará el proceso.

5) xdomainajax

Este plugin utiliza un abordaje interesante utilizando el servicio de Yahoo YQL, en el que cualquier página web (o una parte de ella) se pueden convertir en JSON, por lo que es posible importar en Javascript. Este método es bueno para aquellas situaciones en las que no puede cambiar el formato de origen.

6) flXHR

Esta solución utiliza flash (SWF) para lograr la magia. Podría decir que esta es una manera muy rápida de lograr una implementación casi totalmente de navegador (ya que se basa en el soporte de flash). Este método puede ser ideal para aquellos sitios en los que flash estará presente (seguro). Sin embargo, si su sitio no requiere flash, esa será la principal desventaja ya que los usuarios deberían tener instalado flash para que funcione.

7) xdajax

Esta solución se basa en la aplicación de YUI junto con el enfoque de "flash".

8) Si ninguna de las opciones anteriores es buena para usted, recuerde que todavía puede usar el viejo truco de insertar una etiqueta para importar el código JS.

9) La reducción de la seguridad de IE al mínimo también resuelve el problema. Pero creo que no sería bueno tener un mensaje como este: "Por favor, baje su configuración de seguridad para usar este sitio" ... lol

Espero que esto pueda ayudar a otros en una situación similar.

+0

Redacción excelente. –