Rails HTML Permit Sanitizer未按预期工作问题排查
问题1:为什么img标签及属性被清理?
你的ExampleScrubber初始化方法里的赋值写法犯了一个语法逻辑错误!看这行代码:
self.tags = %w(img), self.attributes = %w(src alt)
在Ruby中,逗号会把右侧的两个表达式打包成一个数组,这就导致self.tags被错误赋值为[["img"], ["src", "alt"]],而不是你期望的%w(img)。PermitScrubber无法识别这种格式的标签列表,所以img根本没被加入允许的标签集合,自然会被清理掉。
修正方法很简单,把赋值拆成两行单独写:
class ExampleScrubber < Rails::Html::PermitScrubber def initialize super self.tags = %w(img) self.attributes = %w(src alt) end end
修改后再运行测试代码,img标签和它的src、alt属性就能被正确保留了。
问题2:实现保留带highlight属性的
的需求
解决第一个问题后,我们来处理你的核心需求:清理所有<div>,只保留带有值为highlight属性的<div>。这里需要注意几个细节:
- 必须先把
div加入允许的标签列表,否则PermitScrubber会直接清理所有div,不管属性是什么; - 重写
allowed_node?时,你原来的注释里把判断符号==写成了赋值符号=,这是语法错误; - 要明确你要检查的是特定属性(比如
class="highlight")还是任意属性的值为highlight。下面的示例假设你要保留任意属性值为highlight的div,同时保留之前的img标签:
class HighlightDivScrubber < Rails::Html::PermitScrubber def initialize super # 允许div和img标签 self.tags = %w(div img) # 允许需要的属性:img的src/alt,div的class、自定义属性等(按需调整) self.attributes = %w(src alt class data-highlight) end def allowed_node?(node) if node.name == "div" # 检查div是否有任意属性的值等于"highlight" node.attributes.any? { |_attr_name, attr_node| attr_node.value == "highlight" } else # 非div标签(比如img)直接保留 true end end end
如果你只需要检查特定属性(比如class="highlight"),可以把判断逻辑改成:
node.attributes["class"]&.value == "highlight"
最后测试一下效果:
@comment.body = "<div>普通div会被清理</div><div class='highlight'>保留的div</div><p><img src='something.jpeg' alt='something'></p>" ActionController::Base.helpers.sanitize(@comment.body, scrubber: HighlightDivScrubber.new) # 输出结果:"<div class='highlight'>保留的div</div><p><img src='something.jpeg' alt='something'></p>"
内容的提问来源于stack exchange,提问作者PandyZhao
相关产品推荐
相关产品推荐

