Rails,如何清理 find_by_sql 中的 SQL

发布于 2024-11-30 18:40:02 字数 993 浏览 1 评论 0原文

有没有办法在rails方法find_by_sql中清理sql?

我尝试过这个解决方案: Ruby on Rails:不使用 find 时如何清理 SQL 字符串?

但它失败了,

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。

第二次编辑:

我想实现“邪恶”的 SQL 代码不会被执行。

在管理面板中,您可以输入查询 -> Update users set admin = true where id = 232 并且我想阻止任何 UPDATE / DROP / ALTER SQL 命令。 只是想知道,这里你只能执行 SELECT。

经过一番尝试后,我得出结论 sanitize_sql_array 不幸的是不要这样做。

Rails 有没有办法做到这一点?

抱歉造成混乱..

Is there a way to sanitize sql in rails method find_by_sql?

I've tried this solution:
Ruby on Rails: How to sanitize a string for SQL when not using find?

But it fails at

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

It throws an error, but sql code is executed and the user with ID 2 now has a disabled account.

Simple find_by_sql also does not work:

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

Edit:

Well my client requested to make that function (select by sql) in admin panel to make some complex query(joins, special conditions etc). So I really want to find_by_sql that.

Second Edit:

I want to achieve that 'evil' SQL code won't be executed.

In admin panel you can type query -> Update users set admin = true where id = 232 and I want to block any UPDATE / DROP / ALTER SQL command.
Just want to know, that here you can ONLY execute SELECT.

After some attempts I conclude sanitize_sql_array unfortunatelly don't do that.

Is there a way to do that in Rails??

Sorry for the confusion..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

天赋异禀 2024-12-07 18:40:02

试试这个:

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

您可以将其保存在变量中并用于您的目的。

Try this:

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

You can save it in variable and use for your purposes.

巷雨优美回忆 2024-12-07 18:40:02

我为此制作了一个小片段,您可以将其放入初始化程序中。

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)

I made a little snippet for this that you can put in initializers.

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

Right now you can escape your query with this:

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

And you can call the query any way you like:

users = User.find_by_sql(query)
栖迟 2024-12-07 18:40:02

稍微通用一些:

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

这个可以让您像键入 where 子句一样调用它,无需额外的括号,并使用数组样式 ?或散列式插值。

Slightly more general-purpose:

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

This one lets you call it just like you'd type in a where clause, without extra brackets, and using either array-style ? or hash-style interpolations.

春花秋月 2024-12-07 18:40:02
User.find_by_sql(["SELECT * FROM users WHERE (name = ?)", params])

来源:http://blog. endpoint.com/2012/10/dont-sleep-on-rails-3-sql-injection.html

User.find_by_sql(["SELECT * FROM users WHERE (name = ?)", params])

Source: http://blog.endpoint.com/2012/10/dont-sleep-on-rails-3-sql-injection.html

握住你手 2024-12-07 18:40:02

尽管此示例适用于 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 中 sanitize_sql_array 方法的 引用: :Base,它通过转义字符串中的单引号来生成正确的查询字符串。例如,punch_line“不要让他们让你失望”将变成“不要让他们让你失望”。

Though this example is for INSERT query, one can use similar approach for UPDATE queries. Raw SQL bulk insert:

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

Here is the reference to sanitize_sql_array method in ActiveRecord::Base, it generates the proper query string by escaping the single quotes in the strings. For example the punch_line "Don't let them get you down" will become "Don\'t let them get you down".

桃酥萝莉 2024-12-07 18:40:02

我更喜欢用关键参数来做。在您的情况下,它可能看起来像这样:

  Model.find_by_sql(["UPDATE user set active = :active where id = :id", active: 0, id: 1])

请注意,您仅将一个参数传递给 :find_by_sql 方法 - 它是一个数组,其中包含两个元素:字符串查询和带参数的哈希(因为它是我们最喜欢的) Ruby,您可以省略大括号)。

I prefer to do it with key parameters. In your case it may looks like this:

  Model.find_by_sql(["UPDATE user set active = :active where id = :id", active: 0, id: 1])

Pay attention, that you pass ONLY ONE parameter to :find_by_sql method - its an array, which contains two elements: string query and hash with params (since its our favourite Ruby, you can omit the curly brackets).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文