我正在看这个 Railscast 插曲,想知道为什么escape_javascript
这里需要调用:
$("#reviews").append("<%= escape_javascript(render(:partial => @review)) %>");
是什么escape_javascript
用的?
根据Rails 文档:
escape_javascript(javascript)
JavaScript 段的转义载体返回和单引号和双引号。
但这对我来说意义不大。
我正在看这个 Railscast 插曲,想知道为什么escape_javascript
这里需要调用:
$("#reviews").append("<%= escape_javascript(render(:partial => @review)) %>");
是什么escape_javascript
用的?
根据Rails 文档:
escape_javascript(javascript)
JavaScript 段的转义载体返回和单引号和双引号。
但这对我来说意义不大。
如果将代码分成两部分,则更容易理解。
第一部分$("#reviews").append("<%= ... %>");
是带有 erb 的 javascript。这意味着<%= ... %>
将被其内部的 ruby 代码返回的任何内容替换。该替换的结果必须是有效的 javascript,否则在客户端尝试处理它时会抛出错误。所以这是第一件事:你需要有效的 javascript。
另一件要考虑的事情是,无论 ruby 生成什么,都必须包含在带有双引号的 javascript 字符串中——注意<%= ... %>
. 这意味着生成的 javascript 将如下所示:
$("#reviews").append("...");
现在让我们检查<%= ... %>
. 有什么作用render(:partial => @review)
?它正在呈现部分代码 - 这意味着它可以呈现任何类型的代码 - html、css ...甚至更多的 javascript!
那么,如果我们的部分包含一些简单的 html 会发生什么,比如这个?
<a href="/mycontroller/myaction">Action!</a>
还记得您的 javascript 将双引号字符串作为参数吗?如果我们简单地用<%= ... %>
那个部分的代码替换,那么我们就会遇到一个问题——紧跟在 之后href=
有一个双引号!javascript 将无效:
// Without escaping, you get a broken javascript string at href
$("#reviews").append("<a href="/mycontroller/myaction">Action!</a>");
为了不发生这种情况,您希望转义这些特殊字符,这样您的字符串就不会被剪切 - 您需要一些生成此内容的东西:
<a href=\"/mycontroller/myaction\">Action!</a>
这有什么escape_javascript
作用。它确保返回的字符串不会“破坏”javascript。如果使用它,您将获得所需的输出:
$("#reviews").append("<a href=\"/mycontroller/myaction\">Action!</a>")
问候!
用户可能会发布恶意代码(恶意用户),如果不进行转义,则可能会被执行,从而允许用户控制您的应用程序。
试试这个:
<% variable = '"); alert("hi there' %>
$("#reviews").append("<%= variable %>");
不太熟悉 rails 的语法,但是如果您不转义,variable
则会显示一个警告框,我认为这不是预期的行为。
如果你看看这里的源代码,它会清楚得多。
该函数完成以下两件事:
它将输入字符串中的字符替换为JS_ESCAPE_MAP 中定义的字符
这样做的目的是确保 javascript 代码正确序列化,而不会干扰嵌入它的外部字符串。例如,如果您有一个双引号的 javascript 字符串,那么字符串文字中的所有引号都必须是单引号,以避免代码被破坏。
当您使用escape_javascript 时,它通常被动态嵌入到另一个字符串或现有的html 中。您需要确保这样做不会使您的整个页面无法呈现。
此响应的某些方面已在其他响应中指出,但我想将所有项目放在一起,包括 javascript 转义和 html 转义之间的区别。此外,一些回应暗示此功能有助于避免脚本注入。我不认为这是这个功能的目的。例如,在您的评论中,如果您的评论有 alert('hi there'),则仅将其附加到节点将不会触发弹出窗口。您没有将它嵌入在页面加载或通过其他事件触发的函数中。仅仅将 alert('hi there') 作为 html 的一部分并不意味着它将作为 javascript 执行。
也就是说,我并不否认脚本注入是不可能的。但是为了避免这种情况,您需要在获取用户数据并将其存储在数据库中时采取措施。您提供的函数和示例与呈现已保存的信息有关。
我希望这会有所帮助并回答您的问题。
因为您不希望用户发布浏览器实际执行的 JavaScript?