2017-03-07 39 views
0

我目前正在为Ruby on Rails 5应用程序中的客户开发徽章系统。我不想将每个徽章硬编码到系统中,而我发现eval()是一种具有危险后果的方法。在Rails 5中为徽章系统取得了eval的条目

这是我目前的策略:

应用程序/模型/ user.rb

class User 
    has_many :awards, dependent: :destroy 
end 

应用程序/模型/ badge.rb

class Badge 
    has_many :awards, dependent: :destroy 

    # name  - string - Name of the badge 
    # icon  - string - URL of badge icon 
    # description - text - Long text description of the badge 
    # criterion - text - boolean operation to eval() to earn badge 
end 

应用程序/模型/ award.rb

class Award 
    belongs_to :user 
    belongs_to :badge 

    def self.automatic_award 
    User.find_each do |user| 
     Badge.find_each do |badge| 
     # If the badge has not been awarded to the user 
     if Award.where(user: user, badge: badge).blank? 
      # If the badge criteria is met 
      if eval(badge.criterion.untaint) 
      Award.create(user: user, badge: badge) 
      # Add method to notify user of award. 
      end 
     end 
     end 
    end 
    end 

end 

我会写一个工作人员定期运行Award.automatic_award方法(每10分钟?)徽章将由管理员在登录安全(不是标准用户)后编写但我担心安全性和受污染条目。

我错过了什么?有没有更好的办法?

回答

0

我认为在数据库中存储代码并允许管理员维护它是一种超级危险的做法。它可以在您的服务器上直接运行任何内容,并绕过部署可执行代码的最佳实践,即暂存和测试它。

我会尝试将徽章需要做的事情分解成可以更好地封装为数据的东西,例如一个规则引擎或特定于领域的语言类型框架,您可以更自信地验证输入并限制其行为。

0

很明显,你会发现这种方法背后的安全问题,但要明确的是,某人(管理员或有权访问编辑徽章标准的人)可以编写类似User.delete_all之类的内容。你相信管理员那么多?

我看其他问题,这种方法(在DB保持代码):

  • 你会如何测试标准码?
  • 没有该标准的版本控制代码
  • 只会引发生产环境中发生的错误,并且您无法在本地进行复制。你怎么知道管理员会写出成功执行的东西?

从给出的例子很难猜出这些标准是什么样子,但是我会把代码放在项目源代码中,即使它意味着为每个徽章编码。我不希望管理员知道如何正确地做到这一点,除非他们是开发人员,并且如果他们没有理由不在项目的来源中明确实施标准。

如果你真的需要灵活一些,你最好设计一些“相对简单的语言”,比如说:comments > 4 && last_login > 3 days。并允许预定义的一组“变量”commesnts, last_login,预定义的一组谓词<, >=, =等。但是像这样的事情根本不简单,商业价值需要证明实施的成本。