我试图在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;)符号后的所有内容。
请帮我弄清楚如何做到这一点。
答案 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 < 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_safe
到true
。所以你应该只传递一个已经安全/转义的字符串。
可能的解决方案可能如下所示:
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;'将保存为<
,这似乎解决了问题。
我在使用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字符<
替换“ <”。应该将其转换为<
,然后呈现为“ <”字符,而不是html。