有没有办法限制ERB(Ruby)中的变量范围?

时间:2014-02-04 05:55:09

标签: ruby-on-rails ruby templates erb

目前我可以这样做:

r = ERB.new('Hi there <%= name %>')
r.result(OpenStruct.new(name: 'Joan').instance_eval{ binding })
# Outputs 'Hi there Joan'

但我也可以这样做(在带有Admin模型的Rails应用程序中运行):

r = ERB.new('<%= Admin.count %>')
r.result(OpenStruct.new.instance_eval{ binding })
# Outputs '10'

换句话说,它可以在调用评估的上下文中访问我的应用程序的所有变量。

有没有办法将变量的范围仅限于我在绑定中提供的范围,例如只有'名字'而没有别的?我想在面向用户的模板工具中使用它。

我也试过这个(根据另一个问题):

class Namespace
  def initialize(hash)
    hash.each do |key, value|
      singleton_class.send(:define_method, key) { value }
    end 
  end

  def get_binding
    binding
  end
end

同样的结果。

1 个答案:

答案 0 :(得分:4)

由于ERB模板被编译为纯Ruby方法并且如此执行,因此您无法限制其访问。通过元编程,模板的作者将能够访问正在运行的Ruby VM中的所有内容并编写任意Ruby代码。

因此,即使您调整传递给模板的变量绑定,也不会限制恶意用户通过将Ruby嵌入ERB来访问您的所有秘密。

如果你真的想要一个安全的模板语言准备好向用户公开,你应该看看Liquid(正如Stefan在评论中所说)或Mustache,两者都旨在提供一个安全的,非评估的模板环境。