如何在HTML文档中安全地嵌入JSON?

时间:2011-08-26 14:08:34

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

在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 &

如果我使用<%=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":"&lt;/script&gt;&lt;b&gt;I can do something bad here&lt;/b&gt;","color":"red"}
];

我在rubyonrails-talk邮件列表上问了这个问题,我现在明白有些人认为这是一个非常糟糕的想法,但在我的情况下,只要没有HTML特殊字符,它就会非常好用。数据。所以我只想让to_json HTML返回的字符串安全,并且仍然可以正确解析它。

更新 根据@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>

4 个答案:

答案 0 :(得分:8)

仅使用@tags.to_json的代码在rails3中运行,如果启用它:

   ActiveSupport.escape_html_entities_in_json = true

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

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

这节省了客户端必须通过$

解析整个事情

答案 1 :(得分:2)

不过,这可行,但在我看来并不是一个好的解决方案:

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

答案 2 :(得分:1)

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

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

(请注意双==和“”)

答案 3 :(得分:1)

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搜索结果的顶部,这就是为什么我决定提供带有更新的评论的原因:)