为什么to_json在Rails 4中自动转义unicode?

jac*_*cob 14 unicode encoding json ruby-on-rails ruby-on-rails-4

Rails 3:

{"a" => "<br/>"}.to_json
=> "{\"a\":\"<br/>\"}"
Run Code Online (Sandbox Code Playgroud)

导轨4:

{"a" => "<br/>"}.to_json
=> "{\"a\":\"\\u003Cbr/\\u003E\"}"
Run Code Online (Sandbox Code Playgroud)

为什么???

它似乎导致错误

Encoding::UndefinedConversionError: "\xC3" from ASCII-8BIT to UTF-8
Run Code Online (Sandbox Code Playgroud)

当我的Rails 3应用程序尝试解析我的rails 4应用程序生成的JSON时.

bob*_*nce 12

为什么???

防范Web应用程序中的常见弱点.如果你在HTML页面中说,例如:

<script type="text/javascript">
    var something = <%= @something.to_json.html_safe %>;
</script>
Run Code Online (Sandbox Code Playgroud)

然后你可能会认为你很好,因为你已经JSON转义了你注入JavaScript的数据.但实际上你并不安全:除了JSON语法之外,你还有周围的HTML语法,而在HTML脚本块中</则是带内信令.实际上,如果@something包含字符串,则会</script>出现跨站点脚本漏洞:

<script type="text/javascript">
    var something = {"attack": "abc</script><script>alert('XSS');//"};
</script>
Run Code Online (Sandbox Code Playgroud)

第一个脚本块在字符串的中间结束(留下未封闭的字符串文字语法错误),第二个<script>脚本块被视为新的脚本块,并且其中的潜在用户提交的内容被执行.

JSON不需要转义<字符,\u003C但它是一个完全有效的替代方案,它可以自动避免这类问题.如果JSON解析器拒绝它,那么这是读者中的一个严重错误.

产生该错误的代码是什么?我不相信错误与<-escaping有关,因为它讨论的是字节0xC3而不是0x3C.这可能表示UTF-8编码内容的字符串未被标记为UTF-8 ...也许您需要force_encoding("UTF-8")输入?

  • 如果你真的需要禁用JSON转义(假设你的情况是安全的注入)你可以这样做:`ActiveSupport.escape_html_entities_in_json = false` (6认同)

mah*_*off 6

您可以保留原始字符串JSON::dump:

JSON::dump "a" => "<br/>"
=> "{\"a\":\"<br/>\"}"

JSON::dump "a" => "x&y"
=> {\"a\":\"x&y\"}" # instead of x\u0026y
Run Code Online (Sandbox Code Playgroud)

小心使用它,因为bobince提到并特别避免任何用户生成的输入(或至少确保已消毒).

这是我遇到的一个合法用途的例子.在辅助函数中生成JavaScript哈希参数:

# application_helper.rb

def widget_js(post)
  options = {
    color: ColorCalculator(post.color).to_rgb_hex,
    ...
  }
  "third_party_widget(#{JSON::dump options});"
end
Run Code Online (Sandbox Code Playgroud)