在我的控制器操作中,我有以下内容:
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注入吗?如果是,我怎样才能让它更安全?如果我正确编写了控制器代码,我也有疑问。如果您有重构控制器代码的建议,请告诉我们,我们将非常感激。非常感谢!
答案 0 :(得分:3)
对于您的查询,您应该尝试使用ActiveRecord
提供的方法或通过Arel
本身(您当前的方法很好)。这将确保您的SQL被正确转义。如果您不想立即了解Arel
的详细信息,可以使用squeel或meta_where等宝石(适用于较旧的导轨)。
我强烈建议您将这些宝石用于满足大多数查询构建需求。您可以使用Arel
直接写出更高级的内容。
我记不起来了,如果你能用matches
语法直接用LIKE
(ActiveRecord.where
),而不需要宝石的帮助。但你绝对可以在Arel
中直接这样做。
articles = Article.arel_table
articles = articles[:category].matches("%#{search}%").
or(articles[:article_type].matches("%#{search}%"))
此时,您可以to_a
articles
或to_sql
使用Article
并使用find_by_sql
将其传递给Article.find_by_sql articles.to_sql
模型。
paginate_by_sql
will_paginate有一个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
只要您传递{{1}},就可以将其他内容绑定到此,因为Rails会将其查询延伸到数据库。