2

SQL インジェクション攻撃の危険を冒さずにこれを行うにはどうすればよいですか?

nearest = Site.minimum('abs(latitude - ' + params[:lat] + ') - abs(longitude - ' + params[:lon] + ')', group: :id)

私はもう試した:

nearest = Site.minimum(['abs(latitude - ?) - abs(longitude - ?)', params[:lat], params[:lon]], group: :id)

しかし、それはうまくいかないようです。ドキュメントには、これを達成する方法があまり明確ではありません。

前もって感謝します!

4

2 に答える 2

2

Rails はsanitize_sql_for_conditions、プレースホルダーを処理するために内部的に使用します。もちろん、そのメソッドは保護されているため、ActiveRecord モデルの外で (クリーンに) 使用することはできません。次を使用して保護を回避できますsend

nearest = Site.minimum(
  Site.send(:sanitize_sql_for_conditions, [
    'abs(latitude - ?) - abs(longitude - ?)',
    params[:lat].to_f, params[:lon].to_f
  ]
)

または、そのロジックをSiteクラスメソッド内に配置して、sanitize_sql_for_conditionsトリックなしで使用できるようにすることもできます。

class Site < ActiveRecord::Base
  def self.whatever_this_is(lat, lon)
    minimum(
      sanitize_sql([
        'abs(latitude - ?) - abs(longitude - ?)',
        lat, lon
      ])
    )
  end
end

そして、コントローラーで:

nearest = Site.whatever_this_is(params[:lat].to_f, params[:lon].to_f)

to_f呼び出しに注意してください。params[:lat]それらを含めない場合は、params[:lon]文字列になり、sanitize_sql_for_conditionsそのように引用されます。

abs(latitude - '11.23') - abs(longitude - '42.6')

データベースは、数値から文字列を減算しようとしているのを見て喜んでいる場合とそうでない場合があるため、意味を正確に伝え、自分で型変換を行うことが最善です。

于 2012-06-01T19:33:51.983 に答える
0

上記の例から何を達成しようとしているのかはわかりませんが、メソッド名を最初の引数として取る最小限のメソッドを不適切に使用しているようです。例えば:

Site.minimum(:latitude)

条件を追加したい場合は、次を使用したいと思います。

Site.where(country: 'USA').group(:id).minimum(:latitude)

繰り返しますが、この例は期待する結果を返しませんが、API の使用方法をよりよく説明する必要があります。

于 2012-06-01T13:35:45.847 に答える