在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返回的字符串安全,并且仍然可以正确解析它。
更新 根据@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>
答案 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_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搜索结果的顶部,这就是为什么我决定提供带有更新的评论的原因:)