1

だから私は動的にフィルターパラメータをwhereメソッドに渡したいので基本的にこれを持っています

@colleges = College.where(@filter).order(@sort_by).paginate(:page => params[:page], :per_page => 20)

そして、@ whereは、このメソッドで作成された文字列です。

def get_filter_parameters
if params[:action] == 'index'
    table = 'colleges'
    columns = College.column_names
else
    table = 'housings'
    columns = Housing.column_names
end

filters = params.except(:controller, :action, :id, :sort_by, :order, :page, :college_id)
filter_keys = columns & filters.keys

@filter = ""
first = true

if filter_keys
    filter_keys.each do |f|
        if first
            @filter << "#{table}.#{f} = '#{filters[f]}'"
            first = false
        else
            @filter << " AND #{table}.#{f} = '#{filters[f]}'"
        end
    end
else
    @filter = "1=1"
end

問題は、生のSQLをそのようなwhereメソッドにドロップすることがどれほど優れているかわからないことです。通常、:state =>'PA'のようなことができることは知っていますが、それを動的に行うにはどうすればよいですか?

アップデート

さて、私は今ハッシュを渡してこれを持っています:

if params[:action] == 'index'
    columns = College.column_names
else
    columns = Housing.column_names
end

filters = params.except(:controller, :action, :id, :sort_by, :order, :page, :college_id)
filter_keys = columns & filters.keys

@filter = {}

if filter_keys
    filter_keys.each do |f|
        @filter[f] = filters[f]
    end
end

それは注射から保護するのに十分でしょうか?

4

1 に答える 1

4

このコードで:

College.where(:state => 'PA')

実際にはハッシュ オブジェクトを渡しています。つまり、これは同等です。

filter = { :state => 'PA' }
College.where(filter)

したがって、文字列の代わりにこのハッシュ オブジェクトを作成できます。

table = "colleges"
field = "state"
value = "PA"

filter = {}
filter["#{table}.#{field}"] = value
filter["whatever"] = 'omg'

College.where(filter)

ただし、これには注意してください。

この情報の出所によっては、ユーザーが提供した文字列をクエリのフィールド名に入れることで、SQL インジェクション攻撃にさらされることになります。適切に使用すると、Rails はクエリの値をサニタイズします。ただし、通常、列名はアプリケーション コードによって固定されており、サニタイズする必要はありません。したがって、この方法で SQL インジェクション保護のレイヤーをバイパスしている可能性があります。

于 2012-10-15T23:26:27.397 に答える