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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7965111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 01:53:28  来源:igfitidea点击:

prevent jquery ajax to execute javascript from script or html response

javascripthtmlajaxjquery

提问by Krzysztof Dk

According to documentation:

根据文档:

If html is specified, any embedded JavaScript inside the retrieved data is executed before the HTML is returned as a string. Similarly, script will execute the JavaScript that is pulled back from the server, then return nothing.

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

How to prevent this? I have js that shall modify the content that is obtained through ajax. Executing it before the html is returned makes no sense as it does not have content to work on (at least in my case).

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

my code:

我的代码:

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);
                }
        });
    }

the script received by ajax is executed twice. First by me in the eval(response), then jquery execute it again (as described in the documentation)

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

回答by Mark Amery

Lee's answeralready adequately addresses the case of HTML responses - scripts embedded in these are notin fact executed automatically unless you add the HTML to the DOM, contrary to the erroneous documentation you quoted.

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

That leaves the other case asked about in your question title - preventing scriptresponses from being executed automatically when received. You can do this easily using the dataTypesetting.

这在您的问题标题中留下了另一种情况 - 防止脚本响应在收到时自动执行。您可以使用该dataType设置轻松完成此操作。

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

Setting dataTypeto 'text'will cause jQuery to disregard the Content-Typeheader returned from the server and treat the response like plain text, thus preventing the default behaviour for JavaScript responses (which is to execute them). From the (recently corrected) docs:

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

The type of pre-processing depends by default upon the Content-Type of the response, but can be set explicitly using the dataType option. If the dataType option is provided, the Content-Type header of the response will be disregarded.

...

If textor htmlis specified, no pre-processing occurs. The data is simply passed on to the success handler, and made available through the responseText property of the jqXHRobject.

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

...

如果指定texthtml,则不进行预处理。数据被简单地传递到成功处理程序,并通过jqXHR对象的 responseText 属性提供。

回答by Lee

jQuery.ajaxdoes notevaluate scripts on return when requesting HTML. The passage you quoted in the question was in fact a long-standing error in the documentation, fixed as of April 2014. The new docs have this to say (emphasis mine):

jQuery.ajax请求 HTML 时评估返回的脚本。您在问题中引用的段落实际上是文档中长期存在的错误,已于 2014 年 4 月修复。新文档有这样的说法(强调我的):

"html": Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.

...

If textor htmlis specified, no pre-processing occurs. The data is simply passed on to the success handler, and made available through the responseText property of the jqXHRobject.

"html": 以纯文本形式返回 HTML;包含的脚本标签在插入 DOM 时进行评估。

...

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

The scripts are evaluated in this case when you call

在这种情况下,当您调用脚本时会评估脚本

edit_dialog.html(response);

If you don't want to evaluate the scripts before inserting your response in to the DOM, you should be able to do something like:

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

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

parseHTMLis the key in that by default it removes script tags. However, be aware that parseHTML is NOT XXS safe and if your source is unknown this is still a security concern.

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

回答by Joey

The documentation states that any embedded Javascript inside the retrieved datawill be executed before the HTML is returned as a string. If you want to then alter whatever you have retrieved using your ajax call, you can do so within the succes property:

该文档指出,检索数据中的任何嵌入 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
  }
});

回答by rgb

That's one of the really annoying things about jQuery that it executes javascript on response. Other frameworks like MooTools disable script execution from responses unless you specifically set that you want them executed which is a much better approach.

这是 jQuery 真正令人讨厌的事情之一,它在响应时执行 javascript。其他框架(如 MooTools)禁用响应中的脚本执行,除非您特别设置要执行它们,这是一种更好的方法。

The only way I could figure to prevent scripts being executed is to add a custom dataFilterIts easy enough but I think it should be default and an ajax option to enable script execution if you want it (I've never had a use for it and other frameworks disable by default for security etc.)

我能想到的阻止脚本被执行的唯一方法是添加一个自定义的dataFilter它很容易但我认为它应该是默认值和一个 ajax 选项来启用脚本执行如果你想要它(我从来没有用过它并且其他框架默认禁用安全等)

Example

例子

$.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##代码##\n\f\r\t\v\b\B]*?)<\/script>/gi, '');
        }
        return data;
    }
    , success: function(data)
    {
        // whatever
    }
});

** UPDATED ** Needs that crazy regex to cover more script tag instances

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

NOTEif dataType hasnt been set in options it will be undefined in dataFilter so I just default it to text for the filter - if you remove that line then it will only work if dataType is explicitly set.

注意如果 dataType 尚未在选项中设置,它将在 dataFilter 中未定义,因此我只是将其默认为过滤器的文本 - 如果您删除该行,那么它仅在明确设置 dataType 时才有效。