在javascript中转义标记
我正在使用骨干,以及在页面加载时传递集合的一般方法
window.router = new Routers.ManageRouter({store: #{@store.to_json});
这很好,效果很好,直到有人决定将文本“ alert("owned")
”添加到其中一个商店字段。 最后一个显然关闭了javascript。 怎么能绕过这个呢?
:javascript $(function() { window.router = new Dotz.Routers.ManageRouter({store: #{@store.to_json}}); Backbone.history.start(); });
以上输出:
//<![CDATA[ $(function() { window.router = new Dotz.Routers.ManageRouter({store: '{"_id":"4f3300e19c2ee41d9a00001c", "points_text":"alert(\"hey\");"'}); Backbone.history.start(); }); //]]>
在块中,任何
后跟一个名称 - 而不仅仅是
- 在语法上都是非法的 - 所以你需要在任何可能出现的地方进行转义。 例如:
:javascript var foo = { store: #{@store.to_json.gsub('','<\/')} };
这将在JS字符串中创建序列<\/
,它被解释为与相同。 确保在gsub替换字符串中使用单引号,或者使用
gsub( "", "<\\/" )
因为Ruby中的单引号和双引号之间存在差异。
显示在行动中:
irb:02.0> s = "foo" # Here's a dangerous string #=> "foo" irb:03.0> a = [s] # Wrapped in an array, for fun. #=> ["foo"] irb:04.0> json = a.to_json.gsub( '', '<\/' ) # Sanitized irb:05.0> puts json # This is what would come out in your HTML; safe! #=> ["foo<\/b>"] irb:06.0> puts JSON.parse(json).first # Same as the original? Yes! Yay! #=> foo
如果您使用的是Rails(或ActiveSupport),则可以启用JSON转义 :
ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true
看到行动:
irb:02.0> a = ["foo"] irb:03.0> puts a.to_json # Without the magic #=> ["foo"] irb:04.0> require 'active_support' irb:05.0> ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true irb:06.0> puts a.to_json # With the magic #=> ["\u003Cb\u003Efoo\u003C/b\u003E"]
它生成的JSON比解决这个特定问题所需的更冗长,但它是有效的。
神奇的词是:
ActiveSupport.escape_html_entities_in_json = true
虽然标记为已弃用,但这仍适用于当前的rails版本(请参阅我的rails c
):
ruby-1.9.3-head :001 > ::Rails.version => "3.2.1" ruby-1.9.3-head :002 > ["<>"].to_json => "[\"<>\"]" ruby-1.9.3-head :003 > ActiveSupport.escape_html_entities_in_json = true => true ruby-1.9.3-head :004 > ["<>"].to_json => "[\"\\u003C\\u003E\"]"
你忘记了”
:javascript $(function() { window.router = new Dotz.Routers.ManageRouter({store: '#{@store.to_json}'}); Backbone.history.start(); });