How to safely embed JSON with </script> in HTML document?

In a Rails 3.1 app, how can I safely embed some JSON data into an HTML document?

Suppose I have this in a controller action:

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

And this in a corresponding view:

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

Then I get this in resulting 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;}
];

which triggers a SyntaxError: Unexpected token & in Chrome

If I remove the Rails' default HTML escaping with <%=raw tags.to_json %> , then it returns this:

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

which, of course, breaks the HTML document with </script> .

Can I somehow tell to_json() method to return something more like this:

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"}
];

I asked this question on rubyonrails-talk mailing list, and I understand now that some people think that's a very bad idea to begin with, but in my case it works very nicely, as long as there are no HTML special chars in the data. So I just want to make the string returned by to_json HTML safe and still have JavaScript parse it properly.

UPDATE: Based on @coreyward comment, I did make it a JS string literal, and that seems to be working great now. Its not quite as elegant of a solution as I was hoping for, but its not too bad either. Here is the code that is working for me:

<% tags = [{name:"tag1", color:"green"}, {name:"</script><b>I can nndo 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>

which results in:

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

Your code using just @tags.to_json works in rails3, if you enable it with:

   ActiveSupport.escape_html_entities_in_json = true

Otherwise, your other option is this:

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

This saves the client having to parse the whole thing through $


顺便说一句,这工作,但不是在我看来很好的解决方案:

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

I think that if you try this it will work:

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

(Notice the double == and the " ")

链接地址: http://www.djcxy.com/p/47928.html

上一篇: 如何在不退出反斜杠的情况下在Rails中输出JSON

下一篇: 如何在HTML文档中安全地嵌入JSON和</ script>?