2014-06-27 32 views
0

我正在使用rails应用程序,并且有两个相当重要的模型,分别是Reminder和Matcher。允许最终用户输入我执行的ruby代码

class Reminder < ActiveRecord::Base 
end 

提醒允许用户设置自己的时间安排做一些事情,让我有所谓的“条件”的文本字段,我允许他们进入自己的Ruby代码。

例如,它们可以输入:

Date.today.friday? 

如果他们想提醒每星期五。我这样做是为了让用户可以创建自己的提醒方式具有最大的灵活性。

然后我有一个计划的cron任务,通过所有的提醒的循环,并检查他们的情况和他们的行动,如:

For reminder in Reminder.all 
    if eval(reminder.condition) 
    # do something 
    end 
end 

的其他用途的情况下这种方法是有我在使用条件一个匹配器模式,这是一个困难一个解释,但我实际上允许用户在这种状态下访问相关的模型数据,例如条件可能是:

@matcher.parent.name == "Father" && @matcher.parent.children.count < 10 

我知道这是很可怕的eval东西用户有输入t,所以我在模型上做了一些验证,以防止一些“讨厌”的词,如“删除,销毁等”。我已经构建了一个带有一些菜单的小型就地代码编辑器,它将代码插入到ACE编辑器中。

我喜欢这种方式,因为它允许用户最大的灵活性。

如何在不使用eval的情况下执行此操作?

回答

0

你不能相信用户输入。阻止某些单词不会阻止像send [“d-e-s-t-r-o-y”.split(' - ')。join('')]或更糟的更有想象力的技术。

如果您真的想要这样做,您可以在不同用户帐户的硬化虚拟机内对其进行远程评估,并验证该命令的stdout输出是否与日期格式匹配。如果你允许任何代码执行,即使那些人也可以避开。

对于更强大的代码,您应该编写一个您想要允许的明确事物的DSL。白名单比黑名单更安全,因为没有人足够聪明地打败其他世界的想象力。

+0

这是一个很棒的例子,我还没有考虑过。我很想去写一个DSL的路径,但我以前没有这样做过。在我开始研究创建DSL所涉及的步骤之前,您能详细阐述一下吗? – user3565039

+0

http://stackoverflow.com/questions/6074915/ruby-creating-a-sandboxed-eval – BookOfGreg

相关问题