【问题标题】:how can i avoid eval in this situation在这种情况下如何避免 eval
【发布时间】:2015-08-12 10:02:24
【问题描述】:

写一个title_tag helper,我想要下面的yml文件结构

index: Hello {{@game.name}}
edit: Edit {{@game.name}} - {{@game.classification}}

到那时我采用 I18n 翻译字符串,需要用实际上下文替换 {{var}}。

title = I18n.t "title_tags.#{namespace}.#{controller_name}.#{action_name}", default: ""

title.scan(/\{\{.*?\}\}/).each do |replace|
  # transform {{@game.name}} => @game.name
  var = replace.gsub(/\{|\}/, "")
  title.gsub! replace, eval(var)
end      

这很好用。另一方面,用户可能会上传一些名称为“system(rm -rf /*)”的游戏,这可能会给我们带来真正的危险?

是否有任何可能以更安全的方式运行?

编辑

感谢 Axel,我可以用这些很酷的东西结束

 title.scan(/\{\{.*?\}\}/).each do |replace|
    var = replace.gsub(/\{|\}/, "")                        

    # catch "resource" (like resource-controller)
    if var.starts_with? "resource"
      @tempresource = resource
      var.gsub!("resource", "@tempresource")
    end

    # @game or @game.name
    if var.starts_with?("@")          
      content = var.split('.').inject(nil){|clazz, method| clazz.nil? ? instance_variable_get(method) : clazz.send(method)}
      title.gsub! replace, content
    end
  end

工作出色!

【问题讨论】:

  • 我了解液体并阅读了 parser.rb 的代码。无法真正弄清楚他们是如何做到的。看起来他们编写了一个自己的函数,可以与 eval 相媲美。也许你有更深的洞察力。顺便说一句:为walle欢呼:-)
  • 我想建议你只是在你的项目中使用 Liquid,而不是自己重新实现它;-)
  • 那是“显而易见的”。很明显我已经尝试过 Liquid::Template.parse("Hallo {{@game.name}}").render 正在返回“Hallo”。也许我弄错了如何使用液体。

标签: ruby-on-rails ruby


【解决方案1】:

您可以使用 send 代替 eval:

content = var.split('.').inject(nil){|clazz, method| clazz.nil? ? instance_variable_get(method) : clazz.send(method)}
title.gsub! replace, content

【讨论】:

  • 对局部变量有什么想法吗?即字符串 =“你好 {{player}}”?幸运的是,我们不应该在 yml 文件中包含这些,但你永远不知道......
  • Binding#local_variable_get
猜你喜欢
  • 1970-01-01
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-21
  • 1970-01-01
  • 2013-07-17
  • 2014-08-24
相关资源
最近更新 更多