Подтвердить что ты не робот

Как безопасно вставлять JSON с</script> в документ HTML?

В приложении 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;}
];

который запускает SyntaxError: Unexpected token & в Chrome

Если я удаляю HTML-эскиз по умолчанию Rails с помощью <%=raw tags.to_json %>, он возвращает это:

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

который, разумеется, разбивает HTML-документ на </script>.

Могу ли я каким-то образом сказать 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, была в безопасности, и JavaScript все равно правильно ее разбирает.

UPDATE: Основываясь на комментарии @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>
4b9b3361

Ответ 1

Ваш код, используя только @tags.to_json, работает в rails3, если вы включите его с помощью:

   ActiveSupport.escape_html_entities_in_json = true

В противном случае, ваш другой вариант:

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

Это избавляет клиента от необходимости разбирать все это через $

Ответ 2

btw, это работает, но не является хорошим решением, на мой взгляд:

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

Ответ 3

Я думаю, что если вы попробуете это, он будет работать:

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

(Обратите внимание на double == и "")