Col*_*ege 15 ruby postgresql ruby-on-rails ruby-on-rails-3 ruby-on-rails-4
在Rails 3中,我可以用来sanitize_sql_array
为那些需要原始SQL查询的偶然时刻清理原始SQL.但是这似乎已经在Rails 4中删除了,或者没有那么多删除,但转移到ActiveRecord :: Sanitization.但是,我现在无法弄清楚如何调用sanitize_sql_array
,那么在Rails 4中清理原始SQL的最佳方法是什么?
我想澄清一下,我在这里讨论完整的原始SQL查询,而不是使用Rail的模型.我知道这不是最佳实践,这正是我必须为此特定查询所做的事情,因为它无法用Rails的漂亮的ActiveRecord接口来表示(相信我,我已经尝试过了).
这是一个示例调用,它明显比我的查询实际上看起来更简单:
query = "SELECT * FROM users
LEFT OUTER JOIN posts ON users.id=posts.user_id
AND posts.topic_id = '#{topic.id}'"
# ^- Obviously bad and very vulnerable, this is what we're trying to fix
ActiveRecord::Base.connection.select_all(query)
Run Code Online (Sandbox Code Playgroud)
gab*_*lal 14
如果您真的需要编写原始SQL,可以使用quote
它来清理它:
conn = ActiveRecord::Base.connection
name = conn.quote("John O'Neil")
title = conn.quote(nil)
query = "INSERT INTO users (name,title) VALUES (#{name}, #{title})"
conn.execute(query)
Run Code Online (Sandbox Code Playgroud)
从Active Record 文档来看,清理 SQL 查询的最佳方法是避免将我们自己的条件构建为纯字符串,换句话说,将参数直接插入到查询中,如下所示:
User.find_by("user_name = '#{user_name}' AND password = '#{password}'")
Run Code Online (Sandbox Code Playgroud)
而是使用数组或散列条件。
数组条件:
Client.where("orders_count = ? AND locked = ?", params[:orders], false)
Run Code Online (Sandbox Code Playgroud)
哈希条件:
Client.where(is_active: true)
Run Code Online (Sandbox Code Playgroud)
一个澄清的例子:
class User < ActiveRecord::Base
# UNSAFE - susceptible to SQL-injection attacks
def self.authenticate_unsafely(user_name, password)
where("user_name = '#{user_name}' AND password = '#{password}'").first
end
# SAFE
def self.authenticate_safely(user_name, password)
where("user_name = ? AND password = ?", user_name, password).first
end
# SAFE
def self.authenticate_safely_simply(user_name, password)
where(user_name: user_name, password: password).first
end
end
Run Code Online (Sandbox Code Playgroud)
以下是一些参考:
归档时间: |
|
查看次数: |
10097 次 |
最近记录: |