Rails Gem sanitize - 如何加入白名单和

Posted

技术标签:

【中文标题】Rails Gem sanitize - 如何加入白名单和【英文标题】:Rails Gem sanitize - How to whitelist & 【发布时间】:2011-12-24 17:47:30 【问题描述】:

现在我们正在使用 sanitize gem:https://github.com/rgrove/sanitize

问题是如果您输入“hello & world”,sanitize 会将其保存在数据库中:

hello & world 

如何将 & 列入白名单。我们希望清理以删除所有可能的恶意 html 和 JS/script 标签。但我们可以允许 & 符号。

想法?谢谢

【问题讨论】:

可能是 Sanitize.clean(html, Sanitize::Config::RELAXED) # => '&' 谢谢,但 RELAXED 几乎允许一切。我想加入白名单,但不知道如何 @bilash.saha 轻松的配置仍将 html-escape 实体,您发布的内容仍将输出“Hello & world” 使用Loofah - 它内置并且完美:) 【参考方案1】:

Sanitize 将始终将输出内容转换为有效 html/xhtml 的 html 实体。

我能确定的最好方法是过滤输出

Sanitize.fragment("hello & world").gsub('&','&') #=> "Hello & world"

【讨论】:

这将解决 & 字符,但不会扩展到 html 引擎使用将转换为实体的所有各种字符。试图跟踪所有这些也会令人头疼。 @agustin 下面的答案是一个更好的解决方案 IMO @ShyamHabarakada Rails 内置的sanitize()strip_tags 的问题是它们不能纠正格式错误的标记,因此不匹配的< 字符会破坏页面布局. strip_tags('Strip <ithese tags') #=> "Strip <ithese tags",但这超出了问题所要求的范围:一种消毒方法,但仍允许使用原始 & 符号。 没错,关于格式错误的标记。我们清理主要是为了防止 HTML 进入不应包含 HTML 的参数。通过内置的 strip_tags 剥离标签对我们来说效果很好。听起来这也是这个问题的场景。我同意,如果您想要全面清理,则需要具有适当 DOM 引擎的更好解决方案。但是对于参数清理,IMO,这似乎有点矫枉过正。【参考方案2】:

改用 strip_tags() 方法。

http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html#method-i-sanitize

【讨论】:

这似乎是问题的正确解决方案(以及我也遇到的问题) 从 rails-html-sanitizer v1.0.3 开始,strip_tags() 将 & 转义为 & github.com/rails/rails-html-sanitizer/issues/28【参考方案3】:

UnixMonkey 的答案是我们最终所做的。

def remove_markup(html_str)
    marked_up = Sanitize.clean html_str

    ESCAPE_SEQUENCES.each do |esc_seq, ascii_seq|
      marked_up = marked_up.gsub('&' + esc_seq + ';', ascii_seq.chr)
    end
    marked_up
  end

其中 ESCAPE_SEQUENCES 是我们不想转义的字符数组。

【讨论】:

【参考方案4】:

从 Rails 4.2 开始,#strip_tags 不会取消编码 HTML 特殊字符

strip_tags("fun & co")
  => "fun & co"

否则你会得到以下结果:

strip_tags("<script>")
  => "<script>"

如果你只想要 & 符号,我建议像 @Unixmonkey 建议的那样过滤输出,并将其保留为 &amp; only

strip_tags("<bold>Hello & World</bold>").gsub(/&amp;/, "&")
  => "Hello & World"

【讨论】:

【参考方案5】:

其他答案都不适合我。我为我的用例找到的最佳方法是使用内置的Loofah gem:

good = '&'
bad = "<script>alert('I am evil');</script>"
greater_than = '>' # << my use case

Loofah.fragment(good).text(encode_special_chars: false)
# => "&"
Loofah.fragment(greater_than).text(encode_special_chars: false)
# => ">"

Loofah.fragment(bad).text(encode_special_chars: false)
# => "alert('I am evil');"

# And just for clarity, without the option passed in:
Loofah.fragment(good).text
# => "&amp;"

但它并非完美无瑕,所以要非常小心:

really_bad = "&lt;script&gt;alert('I am evil');&lt;/script&gt;"
Loofah.fragment(really_bad).text(encode_special_chars: false)
# => "<script>alert('I am evil');</script>"

关于指定方法here的更多信息。

绝对是我需要做的最有效的方法!

【讨论】:

当你说“内置”是什么意思?它内置在 Rails 中吗?它看起来像一个像 sanitize 一样的宝石,这不是我认为内置的。 它包含在 Rails @Dan 中。 gem dependency loofah --reverse-dependencies 给你(除其他外):Used by rails-html-sanitizer-1.3.0 (loofah (~&gt; 2.3))。该 Gem 本身内置在 Rails 中,请参阅 here:“在 Rails 4.2 及更高版本中,此 gem 将负责清理 Rails 应用程序中的 HTML 片段”。

以上是关于Rails Gem sanitize - 如何加入白名单和的主要内容,如果未能解决你的问题,请参考以下文章

Rails sanitize

Rails sanitize() 方法有多好?

如何将 Rails 视图助手提取到 gem 中?

用于 ActiveRecord_Relation 的 Rails 未定义方法“sanitize_sql_array”

如何在 Rails 中清理 sql 片段

Ruby on Rails:.html_safe 和 sanitize() 之间的区别