16

RailsメソッドでSQLをサニタイズする方法はありfind_by_sqlますか?

私はこの解決策を試しました: Ruby on Rails: How to sanitize a string for SQL when not using find?

しかし、それは失敗します

Model.execute_sql("Update users set active = 0 where id = 2")

エラーがスローされますが、SQL コードが実行され、ID 2 のユーザーのアカウントが無効になります。

シンプルfind_by_sqlも機能しません:

Model.find_by_sql("UPDATE user set active = 0 where id = 1")
# => code executed, user with id 1 have now ban

編集:

私のクライアントは、複雑なクエリ(結合、特別な条件など)を作成するために、管理パネルでその機能(SQLによる選択)を作成するように要求しました。だから私は本当にそれをfind_by_sqlしたい。

2番目の編集:

「邪悪な」SQL コードが実行されないようにしたいと考えています。

管理パネルで query ->Update users set admin = true where id = 232と入力すると、UPDATE / DROP / ALTER SQL コマンドをブロックしたいと考えています。ここでは SELECT しか実行できないことを知りたいだけです。

いくつかの試みの後、sanitize_sql_array残念ながらそうしないでください。

Railsでそれを行う方法はありますか??

混乱させて申し訳ありません..

4

6 に答える 6

14

これを試して:

connect = ActiveRecord::Base.connection();
connect.execute(ActiveRecord::Base.send(:sanitize_sql_array, "your string"))

変数に保存して、目的に使用できます。

于 2011-08-22T09:50:08.177 に答える
10

これについては、初期化子に入れることができる小さなスニペットを作成しました。

class ActiveRecord::Base  
  def self.escape_sql(array)
    self.send(:sanitize_sql_array, array)
  end
end

現在、これでクエリをエスケープできます。

query = User.escape_sql(["Update users set active = ? where id = ?", true, params[:id]])

そして、好きな方法でクエリを呼び出すことができます:

users = User.find_by_sql(query)
于 2011-08-22T10:05:57.770 に答える
8

もう少し汎用:

class ActiveRecord::Base  
  def self.escape_sql(clause, *rest)
    self.send(:sanitize_sql_array, rest.empty? ? clause : ([clause] + rest))
  end
end

これを使用すると、where句を入力するのと同じように、余分な角かっこを使わずに、いずれかの配列スタイルを使用して呼び出すことができますか?またはハッシュスタイルの補間。

于 2011-10-20T19:05:08.223 に答える
1

この例は INSERT クエリ用ですが、UPDATE クエリにも同様のアプローチを使用できます。生の SQL 一括挿入:

users_places = []
users_values = []
timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S')
params[:users].each do |user|
    users_places << "(?,?,?,?)" # Append to array
    users_values << user[:name] << user[:punch_line] << timestamp << timestamp
end

bulk_insert_users_sql_arr = ["INSERT INTO users (name, punch_line, created_at, updated_at) VALUES #{users_places.join(", ")}"] + users_values
begin
    sql = ActiveRecord::Base.send(:sanitize_sql_array, bulk_insert_users_sql_arr)
    ActiveRecord::Base.connection.execute(sql)
rescue
    "something went wrong with the bulk insert sql query"
end

ActiveRecord::Base の sanitize_sql_array メソッドへの参照は次のとおりです。文字列内の一重引用符をエスケープして、適切なクエリ文字列を生成します。たとえば、punch_line "Don't let they get you down" は "Don\'t let they get you down" になります。

于 2011-11-04T10:09:07.993 に答える