3

在我的控制器操作中,我有以下内容:

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

我知道如果您直接在查询中使用参数,则可以进行 SQL 注入。在这里,我将参数直接传递给 where 查询Article.search(params[:search])。这容易发生SQL注入吗?如果是,我怎样才能使它更安全?我也怀疑我是否正确编写了控制器代码。如果您对重构控制器代码有任何建议,请告诉我,我们将不胜感激。非常感谢!

4

1 回答 1

3

对于您的查询,您应该尝试使用提供的方法ActiveRecord或通过Arel自身(尽管您当前的方法很好)。这将确保您的 SQL 被正确转义。如果您现在不想详细介绍Arel,可以使用squeelmeta_where 之类的 gem (对于较旧的导轨)。

我强烈推荐这些 gem 来满足您的大多数查询构建需求。任何更高级的内容,您都可以直接使用Arel.

我不记得了,如果您可以在没有 gem 帮助的情况下直接以基本语法执行matches( )。但是你绝对可以直接在.LIKEActiveRecord.whereArel

articles = Article.arel_table
articles = articles[:category].matches("%#{search}%").
  or(articles[:article_type].matches("%#{search}%"))

此时,您可以使用to_aonarticles或 useto_sql并将其传递给您的Article模型find_by_sql

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 将它的查询延迟加载到数据库的方式。

于 2012-08-26T04:40:57.647 回答