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 回答