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

时间:2009-10-25 05:45:57

标签: javascript ruby-on-rails

我正在查看this Railscast episode,并想知道为什么需要拨打escape_javascript的电话:

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

escape_javascript用于什么?

根据the Rails docs

  

escape_javascript(JavaScript的)

     

逃离承运人返回单身和   JavaScript段的双引号。

但这对我来说意义不大。

4 个答案:

答案 0 :(得分:356)

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

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

要考虑的另一件事是,无论ruby生成什么都必须包含在带双引号的javascript字符串中 - 请注意<%= ... %>周围的双引号。这意味着生成的javascript将如下所示:

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

现在让我们检查<%= ... %>内的红宝石部分。 render(:partial => @review)做了什么?它呈现部分 - 这意味着它可以呈现任何类型的代码 - html,css ......甚至更多的javascript!

那么,如果我们的partial包含一些简单的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>")

问候!

答案 1 :(得分:8)

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

试试这个:

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

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

答案 2 :(得分:8)

如果你看一下来源here,它会更加清晰。

此功能完成以下两件事:

  1. 用输入字符串替换输入字符串中的字符 在JS_ESCAPE_MAP

    中定义

    这样做的目的是确保javascript代码 正确序列化而不干扰外部字符串 在其中嵌入。例如,如果你有一个 双引号中的javascript字符串,然后是for中的所有引号 字符串文字必须用单引号来避免代码 断裂。

  2. 该函数还会检查结果字符串是否为html安全。 如果不是那么它会做必要的逃避以确保 字符串变为html安全并返回结果。
  3. 当您使用escape_javascript时,它通常被动态地嵌入到另一个字符串或现有的html中。您需要确保这样做不会使整个页面无法呈现。

    在其他回复中指出了此响应的某些方面,但我想将所有项目放在一起,包括javascript转义和html转义之间的区别。此外,一些回复暗示此功能有助于避免脚本注入。我认为这不是这个功能的目的。例如,在您的评论中,如果您的评论有警报('hi there'),只需将其附加到节点就不会触发弹出窗口。您没有将其嵌入在页面加载或其他事件触发的函数中。仅仅提醒('hi there')作为你的HTML的一部分并不意味着它将作为javascript执行。

    那说我不否认脚本注入是不可能的。但是为了避免在获取用户数据并将其存储在数据库中时需要采取措施。您提供的功能和示例与渲染已保存的信息有关。

    我希望这有助于回答你的问题。

答案 3 :(得分:-2)

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

相关问题