这容易出现SQL注入吗?
在我的控制器操作中,我有以下内容:
def index @articles = (params[:mine] == "true") ? current_user.articles : Article.search(params[:search]) @articles = @articles.sort! { |a,b| b.created_at a.created_at } @articles = Kaminari.paginate_array(@articles).page(params[:page]).per(25) respond_to do |format| format.html format.json { render json: @articles } end end
在模型中:
def self.search(search) if search.present? where("category LIKE ? OR article_type LIKE ?", "%#{search}%","%#{search}%") else find(:all) end end
我知道如果你在查询中直接使用params,那么SQL注入是可能的。 在这里,我通过Article.search(params[:search])
直接将params传递给where查询。 这容易出现SQL注入吗? 如果是,我怎样才能让它更安全? 如果我正确编写了控制器代码,我也有疑问。 如果您有重构控制器代码的建议,请告诉我们,我们将非常感激。 非常感谢!
对于您的查询,您应该尝试使用ActiveRecord
提供的方法或通过Arel
本身(尽管您当前的方法很好)。 这将确保您的SQL被正确转义。 如果你现在不想深入了解Arel
细节,你可以使用像squeel或meta_where这样的gem(对于旧的rails)。
我强烈推荐这些gem,以满足您的大多数查询构建需求。 任何更高级的东西都可以直接使用Arel
写出来。
我不记得了,如果你能用基本的ActiveRecord.where
语法直接进行matches
( LIKE
),而不需要gem的帮助。 但你绝对可以直接在Arel
做到这一点。
articles = Article.arel_table articles = articles[:category].matches("%#{search}%"). or(articles[:article_type].matches("%#{search}%"))
此时,您可以对articles
执行to_a
或使用to_sql
并使用find_by_sql
将其传递给您的Article
模型。
Article.find_by_sql articles.to_sql
will_paginate有一个paginate_by_sql
方法,我认为kaminari
也会有一个(或者至少我认为会这样)。
至于你的控制器代码,我会将任何类型的排序选项传递给数据库(这也适用于你的分页),如果可能的话。
articles.sort('`articles`.created_at DESC')
您现在使用的方法将获取“允许”记录的“全部”然后排序,然后返回您的per_page
限制。 在这种情况下,哪种类型会破坏分页的目的。
至少,尝试重构您当前的设置:
@articles = (params[:mine] == "true") ? current_user.articles : Article.search(params[:search]) @articles = @articles.sort('`articles`.created_at DESC').page(params[:page]).per(25)
只要您传递一个ActiveRelation
,就可以将其他东西绑定到此,因为Rails将它的查询延迟加载到数据库。