有没有办法在rails方法find_by_sql
中清理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那个。
第二次修改:
我想实现'邪恶的'SQL代码不会被执行。
在管理面板中,您可以输入查询 - > Update users set admin = true where id = 232
我希望阻止任何UPDATE / DROP / ALTER SQL命令。
只想知道,在这里你只能执行SELECT。
经过一些尝试,我得出结论sanitize_sql_array
不幸的是不要这样做。
有没有办法在Rails中做到这一点?
很抱歉这个混乱......
答案 0 :(得分:13)
试试这个:
connect = ActiveRecord::Base.connection();
connect.execute(ActiveRecord::Base.send(:sanitize_sql_array, "your string"))
您可以将其保存在变量中并用于您的目的。
答案 1 :(得分: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)
答案 2 :(得分:8)
略微更通用:
class ActiveRecord::Base
def self.escape_sql(clause, *rest)
self.send(:sanitize_sql_array, rest.empty? ? clause : ([clause] + rest))
end
end
这个允许你调用它就像你输入where子句,没有额外的括号,并使用数组样式?或哈希式插值。
答案 3 :(得分:4)
User.find_by_sql([“SELECT * FROM users WHERE(name =?)”,params]) 找到http://blog.endpoint.com/2012/10/dont-sleep-on-rails-3-sql-injection.html
答案 4 :(得分: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
这是reference to sanitize_sql_array method in ActiveRecord::Base,它通过转义字符串中的单引号来生成正确的查询字符串。例如,punch_line“不要让他们让你失望”将成为“不要让他们让你失望”。
答案 5 :(得分:0)
我更喜欢使用关键参数。在您的情况下,可能看起来像这样:
Model.find_by_sql(["UPDATE user set active = :active where id = :id", active: 0, id: 1])
请注意,您仅将一个参数传递给:find_by_sql
方法-它是一个数组,其中包含两个元素:字符串查询和带参数的哈希(因为它是我们最喜欢的Ruby,因此可以省略花括号)。