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

Cam*_*tin 4 ruby templates ruby-on-rails erb

目前我可以做:

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

但我也可以这样做(在具有管理模型的 Rails 应用程序内运行):

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

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

有什么方法可以将变量的范围限制为仅我在绑定中提供的内容,例如仅“名称”而没有其他内容?我想在面向用户的模板工具中使用它。

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

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
Run Code Online (Sandbox Code Playgroud)

相同的结果。

Hol*_*ust 5

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

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

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