阻止jquery ajax从脚本或html响应中执行javascript

时间:2011-11-01 10:23:36

标签: javascript html ajax jquery

根据文件:

  

如果指定了html,则检索内部的任何嵌入式JavaScript   在将HTML作为字符串返回之前执行数据。同样的,   脚本将执行从中拉回的JavaScript   服务器,然后什么也不返回。

如何防止这种情况? 我有js将修改通过ajax获得的内容。在返回html之前执行它是没有意义的,因为它没有内容可以处理(至少在我的情况下)。

我的代码:

function do_ajax(url)
    {
    $.ajax(
        {
        cache: false,
        url : url,
        success: function(response, status, xhr)
            {
            var ct = xhr.getResponseHeader("content-type") || "";
            if (ct.indexOf('script') > -1) {
                try {
                eval(response);
                }
                catch(error) { }
                }
                else
                {
                var edit_dialog = $('<div class="edit_dialog" style="display:hidden"></div>').appendTo('body');
                edit_dialog.html(response);
                edit_dialog.dialog({ modal:true, close: function(event, ui) { $(this).dialog('destroy').remove(); } });
                }

            },
        error:function (xhr, ajaxOptions, thrownError){
                   alert(xhr.status);
                   alert(thrownError);
                }
        });
    }

ajax收到的脚本执行两次。首先由我在eval(响应)中,然后jquery再次执行它(如文档中所述)

4 个答案:

答案 0 :(得分:8)

Lee's answer已经充分解决了HTML响应的问题 - 其中嵌入的脚本而不是实际上是自动执行的,除非您将HTML添加到DOM,这与您引用的错误文档相反

在你的问题标题中留下另一个案例 - 阻止脚本响应在收到时自动执行。您可以使用dataType设置轻松完成此操作。

$.ajax('myscript.js', {
    dataType: 'text',
    success: function (response) {
        // Do something with the response
    }
})

dataType设置为'text'将导致jQuery忽略从服务器返回的Content-Type标头,并将响应视为纯文本,从而阻止JavaScript响应的默认行为(即执行它们)。来自(最近更正的)docs

  

预处理的类型默认取决于响应的Content-Type,但可以使用dataType选项显式设置。如果提供了dataType选项,则将忽略响应的Content-Type标头。

     

...

     

如果指定texthtml,则不会进行预处理。数据只是传递给成功处理程序,并通过jqXHR对象的responseText属性提供。

答案 1 :(得分:3)

jQuery.ajax 在请求HTML时不会评估返回的脚本。您在问题中引用的段落实际上是文档中的长期错误,fixed as of April 2014。新文档有这样说(强调我的):

  

“html”:以纯文本形式返回HTML;包含的脚本标记在插入DOM 时评估为

     

...

     

如果指定了texthtml,则不会进行预处理。数据只是传递给成功处理程序,并通过jqXHR对象的responseText属性提供。

在这种情况下,当您调用

时,将评估脚本
edit_dialog.html(response);

如果您不想在将响应插入DOM之前评估脚本,那么您应该可以执行以下操作:

edit_dialog.html($($.parseHTML(response)));

parseHTML是关键,默认情况下会删除脚本标记。但是,请注意parseHTML不是XXS安全的,如果您的来源未知,这仍然是一个安全问题。

答案 2 :(得分:-1)

文档指出,在将HTML作为字符串返回之前,将执行检索到的数据中的任何嵌入式Javascript 。如果你想改变你使用ajax调用检索的内容,你可以在succes属性中这样做:

$.ajax({
  url: "example.html",
  type: "GET",
  dataType: "html",
  succes: function(data){
     // Example: alert(data);
     // Do whatever you want with the returned data using JS or jQuery methods
  }
});

答案 3 :(得分:-1)

这是关于jQuery的一个非常恼人的事情,它在响应时执行javascript。 像MooTools这样的其他框架会禁止响应中的脚本执行,除非您专门设置了要执行它们的方法,这是一种更好的方法。

我想要阻止脚本执行的唯一方法是添加自定义 dataFilter 它很容易,但我认为它应该是默认和ajax选项,以便在需要时启用脚本执行(我从来没有使用它,而其他框架默认禁用安全等。)

示例

$.ajax('uri',{
    dataFilter: function(data, type)
    {
        type = type || 'text';
        if(type=='html'||type=='text'){
            /*return data.replace(/<script.*>.*?<\/script>/gi, '');*/
            return data.replace(/<script.*?>([\w\W\d\D\s\S\0\n\f\r\t\v\b\B]*?)<\/script>/gi, '');
        }
        return data;
    }
    , success: function(data)
    {
        // whatever
    }
});

**更新** 需要疯狂的正则表达式来覆盖更多的脚本标记实例

注意 如果dataType没有在选项中设置,那么它将在dataFilter中未定义,所以我只是将其默认为过滤器的文本 - 如果删除该行,那么只有在明确设置了dataType时它才会起作用。