Ruby on Rails:允许少于签名'<'内部代码块与sanitize帮助器

时间:2016-04-02 08:58:05

标签: html ruby-on-rails escaping sanitize

我试图在Rails中转义用户生成的内容。我使用raw与清理原始帮助来过滤这样的内容:

raw(sanitize(code, :tags =>   ['<', 'h2','h3','p','br','ul','ol','li','code','pre','a'] ))

内容中允许提及的标签列表。

问题是当我尝试用这样的SQL查询测试它时:

mysql -u sat -p -h localhost database <  data.sql

代码内阻止它删除小于(&lt;)符号后的所有内容。

请帮我弄清楚如何做到这一点。

6 个答案:

答案 0 :(得分:4)

我不相信在Rails中使用默认的清理方法是可行的。

而是尝试使用Sanitize gem(https://github.com/rgrove/sanitize

require 'sanitize'

allowed_elements = ['h2','h3','p','br','ul','ol','li','code','pre','a']
code             = "<pre>mysql -u sat -p -h localhost database < data.sql</pre>"

Sanitize.fragment(code, elements: allowed_elements)
# => <pre>mysql -u sat -p -h localhost database &lt; data.sql</pre>

要使用此功能将已清理的内容保存到数据库,请在模型中添加before_save过滤器,对用户生成的内容进行清理并存储结果,例如

class MyModel < ActiveRecord::Base 
  ALLOWED_ELEMENTS = ['h2','h3','p','br','ul','ol','li','code','pre','a']

  before_save :sanitize_code

  private

  def sanitize_code
    self.code = Sanitize.fragment(code, elements: ALLOWED_ELEMENTS)
  end
end

输出内容时,您只需使用原始视图助手,例如

<%= raw @instance.code %>

答案 1 :(得分:2)

Rails 3为每个String实例添加了html_safe属性。除非html_safe设置为true(简化),否则将打印或插入到数据库的每个字符串都将被转义。 raw的作用实际上是html_safetrue。所以你应该只传递一个已经安全/转义的字符串。

可能的解决方案可能如下所示:

strip_tags(code).html_safe

您可能需要根据用例添加其他检查/字符串替换。

根据您的评论,您可能需要更复杂的版本。你可以尝试替换你想要允许的所有字符,清理字符串,然后反转替换,以避免清理方法消毒超过你真正想要的。尝试这样的事情:

code = "mysql -u sat -p -h localhost database < data.sql"

ALLOWED_SIGNS = {
  :lower_than => "<".html_safe
}

s = code.dup
ALLOWED_SIGNS.each { |k, v| s.sub!(v, "%{#{k}}") }
sanitize(s) % ALLOWED_SIGNS

答案 2 :(得分:2)

似乎整个问题都与数据存储在数据库中的方式有​​关。以前,低于标志'&lt;'正在被保存,但现在它被转义为'&lt;'将保存为&lt;,这似乎解决了问题。

我在使用tinymce-rails WYSIWYG编辑器时意外地理解了这一点,该编辑器正在逃避'&lt;'自动。

@ kieran-johnson的回答可能也是如此,但是tinymce-rails解决了这个问题而没有安装额外的宝石。

感谢所有花时间提供帮助的人。

答案 3 :(得分:1)

这可能会有所帮助,清洁工具有提供白名单标签的选项,并且在清理过程中需要忽略属性

ActionView::Base.full_sanitizer.sanitize(html_string) #Basic Syntax

标签和属性的白名单可以指定为下面的

ActionView::Base.full_sanitizer.sanitize(html_string, :tags => %w(img br p), :attributes => %w(src style))

上面的语句允许标签:img,br和p以及属性:src和style。

答案 4 :(得分:0)

nokogiri gem解决了这个问题:

gem'nokogiri'

Nokogiri::HTML::DocumentFragment.parse('<b>hi</b> x > 5').text
 => "hi x > 5" 

答案 5 :(得分:0)

在通过sanitize方法运行之前,请考虑用ASCII字符&#60;替换“ <”。应该将其转换为&lt;,然后呈现为“ <”字符,而不是html。