IE8 XSS / Jquery проблема - PullRequest
       48

IE8 XSS / Jquery проблема

7 голосов
/ 02 августа 2010

Все отлично работает в Firefox и Chrome, но кроме IE8 (8.0.6001.18702)

Это тестовый код (Jquery 1.4.2) (та же проблема с $ .post):

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

Этот код выполняется в domain1.tld и загружается из domain2.tld следующим образом:

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

Я получаю сообщение «Отказано в доступе» в IE8.Я пытался до сих пор безуспешно:

1) добавление в domain1.tld (код php):

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

2) отключение фильтра XSS в опциях IE8.

Я использую отладчик IE8, и он показывает ошибку в строке 5113:

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

Если вместо вызова $ .get (domain2.tld ...) я вызываю $.get (domain1.tld ...) нет ошибки, которая подтверждает мне, что это проблема "одинаковой политики происхождения" в XSS.

Мое единственное решение (я думаю) это делать через прокси (phpкод), но я бы предпочел не делать этого, так как это влияет на производительность.

Кто-нибудь знает альтернативу / решение этой проблемы?

Примечание: Обновление IE8 не вариант, поскольку яхочу проверить его без обновлений.

Очень похожая проблема для моей: http://forum.jquery.com/topic/jquery-ui-tabs-ie8-and-injecting-elements-into-dom

Ответы [ 3 ]

8 голосов
/ 02 августа 2010

Извините, если мой английский не идеален, как я вижу, я не достаточно ясно ... Одна из моих основных проблем объясняется здесь другим человеком: http://forum.jquery.com/topic/cross-domain-ajax-and-ie

Итак, какая альтернатива существует?

1) XDomainRequest

Лично я считаю, что это лучший способ реализовать межсайтовый скриптинг в IE8 + (так как он поддерживается изначально). Единственная проблема заключается в том, что это только для Microsoft. Но, как и многие другие вещи с семейством IE, мы можем легко расширить функциональность JQuery ajax.

В соответствии с документацией вам необходимо указать дополнительные заголовки в domain1.tld, например, , в PHP , например:

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

Может быть, следующая альтернатива полезна для обеспечения реализации jquery XDomainRequest;

Обновление (a): Существует библиотека XDR (не-jquery), которая "заменяет" класс XHR, чтобы сделать его кросс-браузерным, он основан на Клиентская библиотека pmxdr . Я еще не пробовал.

2) CORS

Единственная проблема с этим плагином заключается в том, что он не является расширением, поскольку его функции называются по-разному, поэтому вам нужно либо изменить коды, либо обернуть этот плагин.

Обновление (b): Я изменил плагин CORS, чтобы упростить его. Проверьте мой другой ответ, чтобы получить код.

3) JsonP в JQuery

Это должен быть самый простой способ решения моей проблемы (так как у меня есть контроль над обоими серверами). В большинстве браузеров поддерживается межсайтовый скриптинг, только если используется формат json (я думаю, что xml также можно использовать). В этом случае используется функция $ .getJSON (). Чтобы это работало, вам нужно указать (как указано в документации) callback =? в URL, например:

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

"?" после того, как «обратный вызов» будет заменен идентификатором ... в вашем php-файле, вам нужно получить этот идентификатор и окружить код Json следующим образом:

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

(я получил этот пример от здесь )

Проблема с этим методом в том, что если вы хотите извлечь только HTML, он должен находиться внутри объекта json, что делает процесс немного более сложным и подавляющим.

4) Плагин jquery.jsonp

Если вам нужны дополнительные проверки и функции для встроенной поддержки JSONP в JQuery, попробуйте этот плагин, который также упростит процесс.

5) xdomainajax

Этот плагин использует интересный подход с использованием сервиса Yahoo YQL, в котором любая веб-страница (или ее часть) может быть преобразована в Json, что позволяет импортировать ее в javascript. Этот метод хорош для тех ситуаций, в которых вы не можете изменить формат источника.

6) flXHR

Это решение использует вспышку (SWF) для достижения магии. Я мог бы сказать, что это очень быстрый способ достижения почти полностью кросс-браузерной реализации (так как он опирается на поддержку Flash). Этот метод может быть идеальным для тех сайтов, на которых будет присутствовать флеш (наверняка). Однако, если ваш сайт не требует флеш-памяти, это становится основным недостатком, поскольку у пользователей должна быть установлена ​​флеш-память, чтобы это работало.

7) xdajax

Это решение основано на реализации YUI вместе с подходом «Flash».

8) Если ни один из предыдущих вариантов не подходит для вас, помните, что вы все еще можете использовать старый прием вставки тега для импорта кода JS.

9) Снижение безопасности IE до минимума также решит проблему. Но я думаю, что было бы нехорошо иметь такое сообщение: «Пожалуйста, уменьшите настройки безопасности, чтобы использовать этот сайт» ... lol

Я надеюсь, что это может помочь другим в подобной ситуации.

5 голосов
/ 03 августа 2010

(я рекомендую проверить список, который я публикую перед этим ответом)

Чтобы облегчить процесс, я взял плагин CORS и изменил его. Вам не нужно изменять существующий код Jquery, если вы просто используете $ .get и $ .post. Я протестировал его в IE8, и он работает, как ожидалось. Для остальных браузеров будут использоваться обычные вызовы JQuery. Вы даже можете добавить этот код по требованию (с условными тегами). Прочитайте первоначальные комментарии для получения дополнительной информации. Надеюсь, это поможет ...

Вот код (сохраните его, например, 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);

Ссылки:

0 голосов
/ 02 августа 2010

Я должен согласиться с Дженди здесь, очень маловероятно, что у вас все получится.Применяется та же политика происхождения (http://en.wikipedia.org/wiki/Same_origin_policy),. Лучше всего написать локальный прокси-сервер, который опрашивает ваш скрипт, а затем разрешить прокси-серверу выполнять междоменные вызовы.

...