Ruby “替代方案”;“评估”;用于ActiveSupport日期解析

Ruby “替代方案”;“评估”;用于ActiveSupport日期解析,ruby,metaprogramming,activesupport,Ruby,Metaprogramming,Activesupport,我的脚本当前接受ActiveSupport日期字符串作为命令行参数: my_script --mindate 1.day 在我的脚本中,我使用eval将其存储到配置中 MyScript.configuration.min_date = eval(min_date_string) 我知道这是非常狡猾和不安全的,因为任何东西都可以传递给eval,但我的替代方案是什么?你想要时间期限吗?我想你可以用 但由于它是自然语言启发法,所以它不能完全准确地定义它将识别哪些类型的字符串。但它会做一些奇特的事情

我的脚本当前接受ActiveSupport日期字符串作为命令行参数:

my_script --mindate 1.day
在我的脚本中,我使用eval将其存储到配置中

MyScript.configuration.min_date = eval(min_date_string)

我知道这是非常狡猾和不安全的,因为任何东西都可以传递给eval,但我的替代方案是什么?

你想要时间期限吗?我想你可以用

但由于它是自然语言启发法,所以它不能完全准确地定义它将识别哪些类型的字符串。但它会做一些奇特的事情,比如“一天四小时”

或者您可以为参数编写自己的非常简单的解析器/解释器。只需按空格(表示“1天”类型的输入)或期间(表示“1天”)类型的输入进行拆分。识别第二个位置的几个单词(“小时”、“分钟”、“天”、“月”、“年”),将它们翻译成秒,将数字乘以翻译成秒的单词。大概有十几行红宝石

或者,您甚至可以利用支持“1.day”等功能的ActiveSupport功能,使其更加简单

  str = "11 hours"
  number, unit = str.split(' ')
  number.to_i.send(unit)
这将允许命令行用户发送他们想要的任何方法到一个数字。我不确定这是否重要。就这一点而言,我不确定原始的
eval
是否真的重要——但我同意你的看法,这是一种不好的做法。就这一点而言,用户输入的
send
可能也是如此,尽管没有那么糟糕

或者你可以让他们发送原始秒数,然后自己计算

my_script --mindate 86400
你意识到,
1.day
最终被转换成标准日的秒数,对吗?我不知道你为什么把几秒钟叫做“mindate”,但那是你的事

编辑或者另一种选择,让他们做:

my_script --mindays 2 --minhours 4 --minminutes 3

或者别的什么

如何调用您的脚本?在运行它的任何机器上都有帐户的用户总是调用它吗?这是否会以某种方式被web服务调用,或者以某种方式,没有访问机器的人可以用自己的参数远程调用它

如果它只由用户调用,而这些用户已经可以访问
ruby
命令或
irb
,那么您就不能让他们通过调用eval来完成他们无法完成的事情


如果是远程调用,您可能不应该使用eval。或者,一个快速而肮脏的解决方案可以是匹配您将使用正则表达式求值的模式。类似于
/^[0-9]+(\.[a-z_0-9]+){,2}$/
的东西将确保在计算之前它在Fixnum文本的2个方法调用之内。

我同意你的观点,这可能没什么大不了的。但安全总比后悔好。当然,有命令行访问权限的人已经可以执行他们想要的任何ruby了。但是你编写了你的实用程序,然后你最终以某种方式使用它,可能会使用它,这样它最终会被远程用户输入传入的参数调用,哦,你刚刚给了远程用户RCE,你可能永远不会意识到,因为它要经过几个步骤,你忘了命令行的arg最后是eval'd。
my_script --mindays 2 --minhours 4 --minminutes 3