1

我想为我正在构建的 cms 加载一个主题.. 我正在考虑有一个名为 name_of_theme.themespec 的文件.. 我会加载这个.. 类似于 Bundler 对 gemspecs 的收费.. 我在想这个里面文件我会有类似的东西:

Theme.new do |t|
  t.value = 'hi'
end

我想在加载脚本后捕获这个主题实例。我应该抓住文件的内容并评估它们吗?这导致我提出一个后续问题,加载文件..和读取内容和评估..我知道'eval'通常被认为是破坏的预兆......也许这个用例好吗?

跟进

根据选择的答案..为什么我会得到:

evaluationContext = Fiber.new {$SAFE = 4; Fiber.yield binding}.resume
 => #<Binding:0x007f85fc8a0fc8> 
a = evaluationContext.eval('puts $SAFE')
=> 0
4

1 回答 1

3

好吧,有一些区别,但如果您已经接受外部代码,则安全漏洞的大小与eval或相同require。在这种情况下,实际上eval可能安全,因为它可以让您控制代码执行的名称空间和安全级别。这很重要,因为,比如说,您的应用程序处理某人的电子邮件密码。require如果你让主题在主命名空间Kernel#gets(所以这里是你如何做这种类型的安全加载:

evaluationContext = Fiber.new {$SAFE = 4; Fiber.yield binding}.resume
theme = evaluationContext.eval(File.read("GrayTheme.themespec"))

注意:从主题调用的任何代码都将在 $SAFE 4 下执行,所以虽然对于大多数事情来说这很好(他们不能调用system("rm -rf /")),但是有少量的 $SAFE 0 代码需要从主题,代码必须在您仍处于安全级别 0 时在 lambda 中创建,然后传递给安全级别 4 中的代码(因为 lambda 保留其安全值)。

编辑:尝试用这个替换 eval 行:

theme = eval(File.read("blahblahba"), evaluationContext)
于 2012-10-21T13:58:16.430 回答