2017-03-07 58 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,預定義的一組謂詞<, >=, =等。但是像這樣的事情根本不簡單,商業價值需要證明實施的成本。