【问题标题】:Safely pass Ruby object to JavaScript安全地将 Ruby 对象传递给 JavaScript
【发布时间】:2011-11-29 01:43:25
【问题描述】:

我有一个包含用户生成字符串的 Ruby 哈希。我需要将此哈希传递给 JavaScript,以便对其进行处理。我尝试过使用 JSON,它在大多数情况下都有效,但是当哈希包含文本 </script> 时会中断。这是在 Chrome 和 FF8 中中断的最简单的代码:

<%
obj = {
  :foo => '</script>'
}
%>
<script type="text/javascript">
var obj = <%= obj.to_json %>; // Results in JS syntax error
</script>

这会产生以下 HTML:

<script type="text/javascript">
var obj = {"foo":"</script>"};
</script>

我还尝试将 JSON 用引号括起来(单引号和双引号),以便可以通过 jQuery.parseJSON() 解析它,但会导致相同的语法错误:

<%
obj = {
  :foo => '</script>'
}
%>
<script type="text/javascript">
var json = '<%= obj.to_json %>'; // Again results in JS syntax error
</script>

语法错误似乎是浏览器试图将&lt;/script&gt; 文本解释为脚本块结尾的结果。我目前的解决方案是将JSON字符串转义为HTML,转义剩余的反斜杠,将其作为字符串写入JS,将HTML转义,然后最后解析JSON:

<%
obj = {
  :foo => '</script>'
}
json = obj.to_json
escaped_json = CGI.escapeHTML(json)
slashed_escaped_json = escaped_json..gsub(/['"\\\x0]/,'\\\\\0')
%>
<script type="text/javascript">
var json = "<%= slashed_escaped_json %>";
json = $('<div/>').html(json).text(); // unescape HTML
var obj = jQuery.parseJSON(json); // parse JSON safely
console.log(obj);
</script>

它有效,但它很难看。有没有更好的办法?我不想去掉&lt;/script&gt;,因为我在将内容呈现在页面上之前将其转义为 HTML 实体。

【问题讨论】:

    标签: javascript ruby json


    【解决方案1】:

    如果您认为这是浏览器的问题,请显示生成的标记,而不是 ruby​​。

    我过去通过在服务器端对 json 进行 base64 编码解决了类似的问题。然后在客户端对其进行解码和json.parsing。

    【讨论】:

    • 我已根据您的评论更新了问题。我考虑过 Base64,但在我丑陋的解决方案中使用了 html 编码。它达到了相同的结果,但我仍然觉得不对:(
    【解决方案2】:

    您是否有任何理由不只是对服务器进行另一个回调以在另一个请求中获取 JSON,如下所示:

    var foo;
    jQuery.get('/your_controller/' + resource_id + '/controller_action.json', null, function(data) {
        try {
         foo = data
        } catch (e) {          
          console.log("Error get data: " + e.message);
        }
     });
    

    我真的不知道您的应用程序是什么,但这是一个可行的选项。

    【讨论】:

    • 这个主意不错,但是为什么可以同时完成两个请求呢?
    【解决方案3】:

    事实证明,这是 Ruby 的“json” gem 中的一个错误。我在 GitHub 上找到了源代码,并在队列中发现了这个拉取请求:

    https://github.com/flori/json/pull/51

    解决办法是把正斜杠转义,得到这样的JSON:

    {"foo":"<\/script>"}
    

    感谢您的所有帮助,我希望此解决方案对其他人有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-03
      • 2019-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多