【问题标题】:How to safely embed JSON with </script> in HTML document?如何在 HTML 文档中安全地嵌入带有 </script> 的 JSON?
【发布时间】:2011-11-04 13:48:28
【问题描述】:

在 Rails 3.1 应用程序中,如何安全地将一些 JSON 数据嵌入到 HTML 文档中?

假设我在控制器动作中有这个:

@tags = [
    {name:"tag1", color:"green"}, 
    {name:"</script><b>I can do something bad here</b>", color:"red"}
]

在相应的视图中:

<script type="text/javascript" charset="utf-8">
    //<![CDATA[
    var tags_list = <%= @tags.to_json %>;
    // ]]>
</script>

然后我在生成的 HTML 中得到这个:

var tags_list = [
    {&quot;name&quot;:&quot;tag1&quot;,&quot;color&quot;:&quot;green&quot;},
    {&quot;name&quot;:&quot;&lt;/script&gt;&lt;b&gt;I can do something bad here&lt;/b&gt;&quot;,&quot;color&quot;:&quot;red&quot;}
];

在 Chrome 中触发 SyntaxError: Unexpected token &amp;

如果我使用<%=raw tags.to_json %> 删除 Rails 的默认 HTML 转义,那么它会返回:

var tags_list = [
    {"name":"tag1","color":"green"},
    {"name":"</script><b>I can do something bad here</b>","color":"red"}
];

当然,它会使用&lt;/script&gt; 破坏 HTML 文档。

我能不能告诉 to_json() 方法返回类似这样的东西:

var tags_list = [
    {"name":"tag1","color":"green"},
    {"name":"&lt;/script&gt;&lt;b&gt;I can do something bad here&lt;/b&gt;","color":"red"}
];

我在 ruby​​onrails-talk 邮件列表上提出了这个问题,我现在明白有些人认为一开始这是一个非常糟糕的主意,但就我而言,只要没有 HTML 特殊字符,它就可以很好地工作数据。所以我只想让to_json HTML 返回的字符串安全,并且仍然让 JavaScript 正确解析它。

更新: 根据@coreyward 的评论,我确实把它变成了一个 JS 字符串文字,现在看起来效果很好。它不像我希望的那样优雅,但也不算太糟糕。这是对我有用的代码:

<% tags = [{name:"tag1", color:"green"}, {name:"</script><b>I can \n\ndo something bad here</b>", color:"red"}] %>

<script type="text/javascript" charset="utf-8">
    //<![CDATA[
    var tags_list = $.parseJSON('<%=j tags.to_json.html_safe %>');
    // ]]>
</script>

导致:

<script type="text/javascript" charset="utf-8">
    //<![CDATA[
    var tags_list = $.parseJSON('[{\"name\":\"tag1\",\"color\":\"green\"},{\"name\":\"<\/script><b>I can \\n\\ndo something bad here<\/b>\",\"color\":\"red\"}]');
    // ]]>
</script>

【问题讨论】:

  • 包含在 JS 字符串文字中的 HTML 不应影响页面的呈现。它应该像字符串中的任何其他字符一样对待。当您使用raw tags.to_json 时,您可能想要调查真正发生了什么。
  • 您正在将 JSON 包装在 &lt;script&gt; 标签中,对吗?只要它在脚本中,HTML 就会被忽略...相信我,您可以在脚本中包含一个 JS 字符串,该脚本具有有效标签的整个页面(&lt;html&gt;&lt;head&gt;.. 等),它不会弄乱渲染。
  • 我的问题中的第二个代码 sn-p 是我如何将它嵌入到 HTML 页面中。所以它在 &lt;script&gt; 标签内,而不是在字符串文字内,而是像原始 JS 对象一样。只要@tags 变量中没有 HTML 特殊字符,这就会很好地工作。
  • @coreyward 你给了我一个想法,我可以让它成为有效的 JS 字符串并用 jQuery 解析它,这实际上让我找到了一个我相当满意的解决方案。感谢那! :) 所以我现在不是在做var tags_list = &lt;%= @tags.to_json %&gt;;,而是在做var tags_list = $.parseJSON('&lt;%=j tags.to_json.html_safe %&gt;');,这让我的工作做得足够好。最初我想在 HTML 中将它作为普通的 JS 对象/哈希,但我宁愿让 jQuery 进行解析,然后我在服务器上为每个对象进行适当的 HTML 转义。这对我来说似乎更通用。
  • 下面的赏金消息应该是:在直接嵌入到 Rails 视图中的 JSON 中,真的没有标准的转义 "&lt;/script&gt;" 字符串的方法吗?

标签: ruby-on-rails json ruby-on-rails-3 html-parsing


【解决方案1】:

顺便说一句,这可行,但在我看来不是一个好的解决方案:

<script type="text/javascript" charset="utf-8">
  //<![CDATA[
  var tags_list = <%=raw @tags.to_json.gsub('/', '\/') %>;
  // ]]>
</script>

【讨论】:

【解决方案2】:

我认为如果你试试这个它会起作用的:

var tags_list = "<%== @tags.to_json.gsub('/', '\/') %>";

(注意双 == 和 " ")

【讨论】:

    【解决方案3】:

    您的代码仅使用 @tags.to_json 在 rails3 中工作,如果您启用它:

       ActiveSupport.escape_html_entities_in_json = true
    

    否则,您的另一个选择是:

       var tags_list = <%= raw @tags.to_json.gsub("</", "<\\/") %>;
    

    这样就省去了客户端通过 $ 解析整个事情的麻烦

    【讨论】:

    • 实际支持转义和&。如果您想安全起见,我认为最好自己也这样做。
    • Google gson(他们的 java json 编码器)很好地用他们的 unicode 对应字符替换以下字符。 \u003e, & \u0026, = \u003d, ' \u0027 这样做的原因是我们作为开发人员倾向于将json放在一堆疯狂的地方(例如属性)。
    【解决方案4】:

    2019年正确的做法是用json_escape函数包裹obj.to_json。 json_escape 直接用于转义 JSON 字符串中的特定 HTML 符号。以下示例来自文档:

    json = JSON.generate({ name: "</script><script>alert('PWNED!!!')</script>"})
    # => "{\"name\":\"</script><script>alert('PWNED!!!')</script>\"}"
    
    json_escape(json)
    # => "{\"name\":\"\\u003C/script\\u003E\\u003Cscript\\u003Ealert('PWNED!!!')\\u003C/script\\u003E\"}"
    
    JSON.parse(json) == JSON.parse(json_escape(json))
    # => true
    

    这个页面似乎出现在 Google 搜索结果的顶部,这就是为什么我决定提供评论和更新:)

    【讨论】:

    • docs for json_escape
    猜你喜欢
    • 2012-12-26
    • 1970-01-01
    • 2013-03-13
    • 2011-04-16
    • 2021-09-07
    • 2012-06-16
    • 2019-06-26
    • 2011-02-15
    • 2020-10-17
    相关资源
    最近更新 更多