Rails, how to sanitize SQL in find_by_sql

匿名 (未验证) 提交于 2019-12-03 01:33:01

问题:

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..

回答1:

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.



回答2:

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) 


回答3:

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.



回答4:

User.find_by_sql(["SELECT * FROM users WHERE (name = ?)", params]) Found at http://blog.endpoint.com/2012/10/dont-sleep-on-rails-3-sql-injection.html



回答5:

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 

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".



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!