如何在 HTML 文档中安全地嵌入带有 </script> 的 JSON?

Posted

技术标签:

【中文标题】如何在 HTML 文档中安全地嵌入带有 </script> 的 JSON?【英文标题】:How to safely embed JSON with </script> in HTML document? 【发布时间】: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;" 字符串的方法吗? 【参考方案1】:

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

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

【讨论】:

注意:另一个相关的堆栈溢出讨论——***.com/questions/1580647/…【参考方案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_jsonjson_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

以上是关于如何在 HTML 文档中安全地嵌入带有 </script> 的 JSON?的主要内容,如果未能解决你的问题,请参考以下文章

如何在一个Html文件中嵌入另一个Html文件

如何在 asp.net Web 应用程序中安全地嵌入 F# 编译器

如何最好地处理带有嵌入式数据库的 Flyway 以进行集成测试?

在 iFrame 中安全地执行 HTML5/Javascript

如何在 Delphi 中将带有图像的 RichText (RTF) 文档转换为 HTML?

带有外部和嵌入式 yaml 的 RMarkdown