Правильный способ выполнения JavaScript, возвращенного через AJAX (без jQuery) - PullRequest
4 голосов
/ 11 ноября 2011

Скажем, я получил ответ на запрос загрузки данных AJAX со смесью JavaScript и HTML, например ::

<script>window.alert('Hello World!');</script>
<p>This is a paragraph. Lorem ipsum dolor sit amet...</p>

Если я просто помещу этот ответ в div или другой контейнер, скрипт не будет выполнен автоматически. Я знаю, что это можно сделать с помощью функции eval() (как отмечено в приведенном ниже примере), но eval - это зло, так как я могу сделать это правильно? Примечание: Я не использую jQuery.

Ниже приведен пример загрузчика AJAX:

function Load(id,url){
    var ajax=new XMLHttpRequest();
    ajax.onreadystatechange=function(){
        if(ajax.readyState!=4)return;
        var obj=document.getElementById(id);
        if(!obj)return;
        obj.innerHTML=ajax.responseText;

        // load any scripts
        var s=obj.getElementsByTagName('script');
        for(var i=0;i<s.length;++i)window.eval(s[i].innerHTML); // <-- bad
    }
    ajax.open("GET",url,true);
    ajax.send(null);
}

Ответы [ 3 ]

3 голосов
/ 11 ноября 2011

Обратите внимание, что вы принимаете ввод от пользователя и запускаете его в контексте сценария на вашем сайте. Таким образом, сценарий может выполнять все, что может выполнять JavaScript, выполняемый в вашем браузере / домене (включая кражу файлов cookie, XSS, вредоносное ПО и т. Д.).

Единственное, что вы можете реально сделать, чтобы снизить риски, - это не проверять () предоставленный пользователем контент. Я бы предложил рассмотреть следующие альтернативы:

  1. Используйте iframe в качестве среды для запуска скрипта пользователя: http://dean.edwards.name/weblog/2006/11/sandbox/
  2. Используйте Каху. Он позволяет веб-сайтам безопасно встраивать веб-приложения DHTML от третьих лиц и обеспечивает широкое взаимодействие между страницей встраивания и встроенными приложениями. Он использует модель безопасности объектных возможностей, чтобы обеспечить широкий спектр гибких политик безопасности. http://code.google.com/p/google-caja/
2 голосов
/ 11 ноября 2011

eval в этом сценарии не особенно вреден, он не сильно отличается от, скажем, динамического добавления тега сценария, который загружает файл .js и запускает его.Тем не менее, есть и другие варианты, например, вы можете динамически создать тег сценария, создать текстовый узел с содержимым тега сценария, который вы перетащили вниз, и добавить его в документ.В отличие от метода innerHTML, он фактически запускает содержимое.Единственное преимущество перед eval в том, что вы можете получить более значимую трассировку стека и т. Д., Если она дает сбой или имеет синтаксическую ошибку.

var newScriptTag = document.createElement('script');
newScriptTag.appendChild(document.createTextNode(
     origScriptTag.innerHTML)
document.body.appendChild(newScriptTag);
0 голосов
/ 06 февраля 2014

Я решил это сегодня, поместив свой JavaScript внизу HTML ответа.

У меня был AJAX-запрос, который возвращал группу HTML, которая отображалась в оверлее. Мне нужно было прикрепить событие click к кнопке в возвращенном ответном HTML / оверлее. На обычной странице я бы обернул свой JavaScript в "window.onload" или "$ (document) .ready", чтобы он прикреплял обработчик событий к объекту DOM после рендеринга DOM для нового наложения, но поскольку это был ответ AJAX, а не загрузка новой страницы, это событие никогда не происходило, браузер никогда не выполнял мой JavaScript, мой обработчик событий никогда не привязывался к элементу DOM, и моя новая функциональность не работала. Опять же, я решил «выполнить JavaScript в проблеме ответа AJAX», не используя «$ (document) .ready» в заголовке документа, а разместив свой JavaScript в конце документа и запустив его после HTML / DOM визуализирован.

...