我想为我正在构建的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
答案 0 :(得分: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的代码(因为lambdas保留其安全值)。
编辑:尝试用以下代码替换eval行:
theme = eval(File.read("blahblahba"), evaluationContext)