Rails,如何在find_by_sql中清理SQL
有没有办法在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
编辑:
好吧,我的客户端要求在管理面板中创建该function(由sql选择)以进行一些复杂的查询(连接,特殊条件等)。 所以我真的想find_by_sql那个。
第二编辑:
我想实现’邪恶的’SQL代码不会被执行。
在管理面板中,您可以键入查询 – > Update users set admin = true where id = 232
,我想阻止任何UPDATE / DROP / ALTER SQL命令。 只是想知道,在这里你只能执行SELECT。
经过一些尝试,我得出结论sanitize_sql_array
不幸的是不要这样做。
有没有办法在Rails中做到这一点?
对困惑感到抱歉..
试试这个:
connect = ActiveRecord::Base.connection(); connect.execute(ActiveRecord::Base.send(:sanitize_sql_array, "your string"))
您可以将其保存在变量中并用于您的目的。
我为此做了一个小片段,你可以放入初始化器。
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)
略多一般用途:
class ActiveRecord::Base def self.escape_sql(clause, *rest) self.send(:sanitize_sql_array, rest.empty? ? clause : ([clause] + rest)) end end
这个让你调用它就像你输入where子句,没有额外的括号,并使用数组样式? 或散列样式插值。
User.find_by_sql([“SELECT * FROM users WHERE(name =?)”,params])发现于http://blog.endpoint.com/2012/10/dont-sleep-on-rails-3-sql-injection html的
虽然此示例适用于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“不要让他们让你失望”将成为“不要让他们让你失望”。