为什么escape_javascript在渲染部分之前?

我正在看这个Railscast插曲 ,想知道为什么在这里需要调用escape_javascript

 $("#reviews").append("<%= escape_javascript(render(:partial => @review)) %>"); 

什么是escape_javascript用于?

根据Rails文档 :

escape_javascript(JavaScript的)

Escape运营商返回和JavaScript段的单引号和双引号。

但这对我来说没有多大意义。

因为你不希望用户发布浏览器实际执行的JavaScript?

如果将代码分为两部分,则更容易理解。

第一部分$("#reviews").append("<%= ... %>"); 是JavaScript与erb。 这意味着<%= ... %>将被其内部的ruby代码返回。 该replace的结果必须是有效的JavaScript,否则当客户端尝试处理时会引发错误。 所以这是第一件事:你需要有效的JavaScript

另一件要考虑的事情是,无论使用何种ruby生成,都必须包含在带有双引号的JavaScriptstring中 – 注意<%= ... %>周围的双引号。 这意味着生成的JavaScript将如下所示:

 $("#reviews").append("..."); 

现在让我们来看看<%= ... %>里面的ruby部分。 什么render(:partial => @review)呢? 它是呈现一个部分 – 这意味着它可以呈现任何types的代码 – HTML,CSS …甚至更多的JavaScript!

那么,如果我们的部分包含一些简单的HTML,像这样呢?

 <a href="/mycontroller/myaction">Action!</a> 

请记住,您的JavaScript是一个双引号的string作为参数? 如果我们简单地用该部分的代码replace<%= ... %> ,那么我们有一个问题 – 在href=之后立即有一个双引号! 该javascript将无效:

 // Without escaping, you get a broken javascript string at href $("#reviews").append("<a href="/mycontroller/myaction">Action!</a>"); 

为了避免这种情况的发生,你想逃避这些特殊字符,所以你的string不会被剪切 – 你需要的东西,而不是产生这个:

 <a href=\"/mycontroller/myaction\">Action!</a> 

这是escape_javascript所做的。 它确保返回的string不会“打破”JavaScript。 如果你使用它,你会得到所需的输出:

 $("#reviews").append("<a href=\"/mycontroller/myaction\">Action!</a>") 

问候!

用户可能会发布恶意代码(恶意用户),如果未转义,可能会被执行,从而允许用户控制您的应用程序。

尝试这个:

 <% variable = '"); alert("hi there' %> $("#reviews").append("<%= variable %>"); 

不是很熟悉rails的语法,但是如果你不转义variable那么会显示一个警告框,我不认为这是行为。

如果你看这里的来源,它会更清晰。

这个function完成以下两件事:

  1. 它将inputstring中的字符replace为JS_ESCAPE_MAP中定义的字符

    这样做的目的是为了确保JavaScript代码正确序列化,而不会干扰它所embedded的外部string。 例如,如果在双引号中有一个javascriptstring,则string文字中的所有引号都必须用单引号引起,以避免代码中断。

  2. 该函数还检查结果string是否安全。 如果不是,那么它会进行必要的转义,以确保string变为html安全并返回结果。

当你使用escape_javascript时,它通常被dynamic地embedded到另一个string或现有的html中。 你需要确保这样做不会使整个页面不呈现。

其他回复指出了这个回应的一些方面,但我想把所有的项目一起包括在JavaScript转义和html转义之间的区别。 此外,一些回应暗示此function有助于避免脚本注入。 我不认为这是这个function的目的。 例如,在您的评论中,如果您的评论有警报(“您在那里”),只需将其附加到节点不会触发popup窗口。 您没有将其embedded在页面加载或通过其他事件触发的函数中。 只是警告('你好')作为你的HTML的一部分,并不意味着它会执行为JavaScript。

这就是说我不否认脚本注入是不可能的。 但为了避免这一点,您需要采取措施,当你把用户数据存储在你的数据库。 您提供的function和示例与呈现已保存的信息有关。

我希望这有助于解决你的问题。

它不会执行你正在渲染的JavaScript