【问题标题】:prevent jquery ajax to execute javascript from script or html response防止 jquery ajax 从脚本或 html 响应中执行 javascript
【发布时间】:2011-12-19 09:21:14
【问题描述】:

根据文档:

如果指定了 html,则检索到的任何嵌入的 JavaScript data 在 HTML 作为字符串返回之前执行。相似地, 脚本将执行从 服务器,然后什么也不返回。

如何预防? 我有 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(response) 中,然后 jquery 再次执行它(如文档中所述)

【问题讨论】:

  • 你有你的代码示例吗?
  • 上面添加的代码。所以,当我收到脚本时,它会执行两次。当我注释掉 eval(response) 时,它由 jquery 执行
  • 您是否在 url 中传递 GET 数据?
  • 是的,我用 url 传递 GET 数据
  • “它没有可处理的内容”到底是什么意思?您的意思是您正在检索的 js 引用了当前页面上的元素吗?

标签: javascript html ajax jquery


【解决方案1】:

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

这留下了在您的问题标题中询问的另一种情况 - 防止 script 响应在收到时自动执行。您可以使用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 属性提供。

【讨论】:

    【解决方案2】:

    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 安全的,如果您的来源未知,这仍然是一个安全问题。

    【讨论】:

      【解决方案3】:

      这是关于 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 时才有效。

      【讨论】:

      • 在我看来,这在任何情况下都不是正确的解决方案。请求 JavaScript 文件时,使用 dataType: 'text' 足以阻止其执行。请求 HTML 时,结果中的脚本不会被执行,除非/直到您将 HTML 插入 DOM,所以如果您想自动清除脚本,最好的方法是执行 $response = $(response); $response.find('script').remove(); 然后使用已清除的 @从那时起,987654325@ 而不是原始 HTML。如果你按照自己的方式去做,Zalgo will get you
      • 另外,关于安全性 - 请注意,删除脚本标签不足以呈现来自不受信任来源的 HTML 以安全插入 DOM,因为它可能包含内联事件处理程序(例如 &lt;div onmouseover="alert('haxored u!!1')"&gt; )
      【解决方案4】:

      文档指出,任何在检索到的数据中嵌入的 Javascript 都将在 HTML 作为字符串返回之前执行。如果您想更改使用 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
        }
      });
      

      【讨论】:

      • 当我只收到 js (dataType:'js'),并且在成功函数中我对响应进行 eval 时,它会执行两次。首先是我的评估,然后是文档中描述的 jquery 本身。与 html 类似。
      • 为什么需要使用ajax调用来只接收JS?此外,js 不是允许的数据类型。允许的数据类型为:xmlhtmljsonjsonpscripttext
      • 我有一个执行 ajax 调用的函数 do_ajax(url)。它检查它收到的内容。如果是 js 则执行,如果是 html 则创建 jqueryui 对话框并将内容放入对话框中。
      • 我同意 js 不是正确的数据类型。只是这里的帖子中的一个错字。我的意思是 dataType:'script' 我无法更改 dataType 因为我不知道我会收到什么响应。
      • 我不建议您使用这样的功能,因为您可能会丢失大量数据或导致不必要的行为。无需通过 ajax 调用外部 javascript 方法,只需将它们包含在您的代码中,您就可以随时调用它们。没有像你描述的那样的变通功能。
      猜你喜欢
      • 2011-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多