Rails Gem sanitize - 如何进行白名单处理?

14

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

问题是,如果您输入了 "hello & world" ,那么sanitize会将其保存到数据库中:

hello & world 

如何将 & 加入白名单。我们想要消除所有可能的恶意HTML和JS/Script标签,但是我们允许使用这个&符号。

有什么建议吗?谢谢


可能是 Sanitize.clean(html, Sanitize::Config::RELAXED)

=> '&'

- bilash.saha
谢谢,但是RELAXED允许几乎所有东西。我想要白名单,但就是找不到如何实现。 - AnApprentice
@bilash.saha 放松的配置仍然会html转义实体,你发布的内容仍然会输出“Hello & world”。 - Unixmonkey
使用 Loofah - 它是内置的,非常完美 :) - SRack
5个回答

6

Sanitize会始终将输出内容转换为HTML实体,以确保有效的HTML/XHTML。

我认为最好的方法是过滤输出内容。

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

2
这将解决&字符,但无法扩展到html引擎使用的所有各种字符转换为实体。试图跟踪所有这些将是一个头痛的问题。@agustin在下面的答案中是我认为更好的解决方案。 - Shyam Habarakada
1
@ShyamHabarakada 我对Rails内置的sanitize()strip_tags方法存在的问题是它们不能纠正格式不正确的标记,因此未匹配的<字符会破坏页面布局。 strip_tags('Strip <ithese tags')#=>“Strip <ithese tags”但这超出了问题所要求的:一种对内容进行清理的方式,同时仍允许原始的安带符号。 - Unixmonkey
没错,关于格式不正确的标记。我们主要进行消毒是为了防止HTML进入不应该有HTML的参数中。通过内置的strip_tags去除标记对我们来说很有效。听起来这也是这个问题的情况。我同意,如果你想要完全的消毒,需要一个具有适当DOM引擎的更好的解决方案。但对于参数消毒,我认为那似乎有些过度了。 - Shyam Habarakada

3

这似乎是针对问题(我也遇到的问题)的正确解决方案。 - Shyam Habarakada
5
自rails-html-sanitizer v1.0.3起,strip_tags()将 & 转义为 &。https://github.com/rails/rails-html-sanitizer/issues/28 - Andrew Hood

2

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是一个字符数组,包含我们不想转义的字符。


2

其他答案对我都没用。我发现适用于我的情况最好的方法是使用内置的Loofah宝石:

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>"

关于指定方法的更多信息在这里

对于我需要做的事情来说,这绝对是最有效的方法!


“内置”这个词是什么意思?它是内置于Rails中的吗?看起来像sanitize一样的gem,不是我认为的内置。 - Dan
1
它已经包含在Rails中了@Dan。gem dependency loofah --reverse-dependencies会给你(其中之一):Used by rails-html-sanitizer-1.3.0 (loofah (~> 2.3))。该Gem本身已经内置于Rails中,参见此处:"在Rails 4.2及以上版本中,该Gem将负责清理Rails应用程序中的HTML片段"。 - SRack

1
截至Rails 4.2,#strip_tags不会解码HTML特殊字符。
strip_tags("fun & co")
  => "fun &amp; co"

否则你会得到以下内容:
strip_tags("&lt;script&gt;")
  => "<script>"

如果你只需要“&”符号,我建议按照@Unixmonkey的建议过滤输出,并仅保留&
strip_tags("<bold>Hello & World</bold>").gsub(/&amp;/, "&")
  => "Hello & World"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接