如何在 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 = [
"name":"tag1","color":"green",
"name":"</script><b>I can do something bad here</b>","color":"red"
];
在 Chrome 中触发 SyntaxError: Unexpected token &
如果我使用<%=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"
];
当然,它会使用</script>
破坏 HTML 文档。
我能不能告诉 to_json() 方法返回类似这样的东西:
var tags_list = [
"name":"tag1","color":"green",
"name":"</script><b>I can do something bad here</b>","color":"red"
];
我在 rubyonrails-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 包装在 <script>
标签中,对吗?只要它在脚本中,HTML 就会被忽略...相信我,您可以在脚本中包含一个 JS 字符串,该脚本具有有效标签的整个页面(<html><head>
.. 等),它不会弄乱渲染。
我的问题中的第二个代码 sn-p 是我如何将它嵌入到 HTML 页面中。所以它在 <script>
标签内,而不是在字符串文字内,而是像原始 JS 对象一样。只要@tags
变量中没有 HTML 特殊字符,这就会很好地工作。
@coreyward 你给了我一个想法,我可以让它成为有效的 JS 字符串并用 jQuery 解析它,这实际上让我找到了一个我相当满意的解决方案。感谢那! :) 所以我现在不是在做var tags_list = <%= @tags.to_json %>;
,而是在做var tags_list = $.parseJSON('<%=j tags.to_json.html_safe %>');
,这让我的工作做得足够好。最初我想在 HTML 中将它作为普通的 JS 对象/哈希,但我宁愿让 jQuery 进行解析,然后我在服务器上为每个对象进行适当的 HTML 转义。这对我来说似乎更通用。
下面的赏金消息应该是:在直接嵌入到 Rails 视图中的 JSON 中,真的没有标准的转义 "</script>"
字符串的方法吗?
【参考方案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_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以上是关于如何在 HTML 文档中安全地嵌入带有 </script> 的 JSON?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 asp.net Web 应用程序中安全地嵌入 F# 编译器
如何最好地处理带有嵌入式数据库的 Flyway 以进行集成测试?
在 iFrame 中安全地执行 HTML5/Javascript