2010-06-09 57 views
30

我必須清理sql查詢的一部分。我可以這樣做:如何清理Rails中的SQL片段

class << ActiveRecord::Base 
    public :sanitize_sql 
end 

str = ActiveRecord::Base.sanitize_sql(["AND column1 = ?", "two's"], '') 

但它不安全,因爲我暴露了受保護的方法。什麼是更好的方法來做到這一點?

+3

你可以給我們多一點上下文嗎? 'sanitize_sql'和朋友經常在AR :: Base派生類中被調用,而不需要改變可視性 – pilcrow 2010-06-09 19:59:57

+0

這是一個很好的和有效的點。當我使用某人的私有或受保護的方法時,我只是很畏縮。 – dimus 2010-06-11 11:55:19

回答

3

您可以通過調用間接繞過protected內斯方法:

str = ActiveRecord::Base.__send__(:sanitize_sql, ["AND column1 = ?", "two's"], '') 

...至少會饒你具有以重塑該方法public

(我有點懷疑,你實際上需要做到這一點,但上面會奏效。)

+0

一個用途是清理sql命令發送到facebook api – lulalala 2012-04-17 08:43:11

+17

不是一個使用send來解決方法的保護性質的巨大粉絲。 – chug2k 2013-02-26 21:15:59

13

的ActiveRecord :: Base.connection.quote確實對Rails 3.x中招

41

你可以使用:

ActiveRecord::Base::sanitize(string) 
+0

適用於Rails 2.3.8 – MrYoshiji 2014-02-24 21:43:58

+9

這代表到'ActiveRecord :: Base.connection.quote'(至少在Rails 4中) – 2015-05-30 15:29:50

+1

這個方法在[PR 26000](https://github.com/rails/rails/pull/26000) – Scudelletti 2017-03-07 14:45:12

4

這個問題沒有明確規定,答案必須來自ActiveRecord也沒有明確指出其Rails的版本是應該的。出於這個原因(因爲它是頂部和爲數不多的)如何消毒Rails中參數的答案...


這裏,與軌道4有效的解決方案:

ActiveRecord::Sanitization::ClassMethods你有sanitize_sql_for_conditions及其兩個其他別名sanitize_conditionssanitize_sql。三者確實完全一樣。

sanitize_sql_for_conditions

接受一個數組,散列,或SQL條件字符串,並進行消毒 它們放入一個有效的SQL片段爲WHERE子句

此外,在ActiveRecord的你有

sanitize_sql_for_assignment

接受一個數組,哈希,或SQL條件串並進行消毒它們 成一個SET子句一個有效的SQL片段

  • 上述方法包括在ActiveRecord的::默認Base和因此被包括在任何ActiveRecord的模型

此外,然而,在ActionController的你有ActionController::Parameters它允許你

選擇哪些屬性應該被列入白名單大規模更新和 從而防止不小心暴露的是其不應該暴露。 爲此提供了兩種方法:要求許可

params = ActionController::Parameters.new(user: { name: 'Bryan', age: 21 }) 
req  = params.require(:user) # will throw exception if user not present 
opt  = params.permit(:name)  # name parameter is optional, returns nil if not present 
user = params.require(:user).permit(:name, :age) # user hash is required while `name` and `age` keys are optional 

「參數魔法」被稱爲強參數(docs here),你可以用它發送到模型前消毒的控制器參數。

  • 上述方法是通過在缺省包括ActionController::Base因此被包含在任何的Rails控制器

我希望能幫助任何人,如果只是爲了學習和揭祕Rails! :)

+0

'require'和'permit'是否針對SQL注入清理參數,或者只是驗證它們的存在? – Matt 2016-08-01 15:18:05

+2

它不會消毒,只是驗證是否存在 – Jimmy 2016-08-02 14:22:56

+2

@Matt:吉米是正確的,「需要」和「許可」不會自行消毒。但是'ActionController :: Parameters.new'會消毒,所以你的所有控制器應該已經在消毒所有的參數。當我有時間後,我會更新我的答案,因爲我也發現了這個非常酷的寶石,名爲rails-html-sanitizer https://github.com/rails/rails-html-sanitizer – 2016-08-09 21:52:00