Tal*_*boy 16 ruby postgresql activerecord ruby-on-rails ruby-on-rails-5
我已经在一段时间内阅读了关于各种SO线程,指南等的内容......但所有答案都是矛盾和矛盾的.
似乎有很多类似的方法,很多答案都说使用不同的方法.
sanitize
sanitize_conditions
sanitize_sql
sanitize_sql_array
sanitize_sql_for_assignment
sanitize_sql_for_conditions
sanitize_sql_hash
sanitize_sql_hash_for_assignment
sanitize_sql_hash_for_conditions
sanitize_sql_like
我正在尝试编写一个"原始查询"适配器,它允许我运行原始的Postgres查询,但允许我插入来自危险用户输入的我自己的参数.
我不能在这几个实例中使用AR,因为我正在进行复杂的纬度/经度计算,聚合函数,复杂子查询等.
到目前为止,我尝试了两种方法:
方法1
对于这种方法,我不知道是否sanitize
是上述的最佳选择,或者它是否适用于100%的情况......(我只使用Postgres)
class RawQuery
def exec(prepared, *params)
prepared = query.dup
params.flatten.each_with_index do |p, i|
prepared.gsub!("$#{i + 1}", ActiveRecord::Base.sanitize(p))
end
ActiveRecord::Base.connection.exec_query(prepared)
end
end
Run Code Online (Sandbox Code Playgroud)
琐碎的用法示例(当然通常不会这么简单,或者我只会使用AR):
RawQuery.new.exec('SELECT * FROM users WHERE name = $1', params[:name])
此外,它似乎sanitize
代表quote
.但根据这篇SO帖子说它只是用单引号包装东西并不安全......所以我不知道.
方法2
我不确定这是否同样安全,但它似乎使用了一个实际的PG准备功能(我假设它是100%安全的).唯一的问题是rails不会将其打印到控制台,也不包括SQL执行时间(这会破坏我的分析工具).
class RawQuery
def prepare(query, *params)
name = "raw_query_#{SecureRandom.uuid.gsub('-', '')}"
connection = ActiveRecord::Base.connection.raw_connection
connection.prepare(name, query)
connection.exec_prepared(name, params)
end
end
Run Code Online (Sandbox Code Playgroud)
使用方式相同:
RawQuery.new.prepare('SELECT * FROM users WHERE name = $1', params[:name])
一种方法比另一种更安全吗?100%安全吗?
我的应用程序总是远远超出Rails的SQL能力范围,我需要一个好的库,我可以包含在我认为完全安全的所有项目中.
Pau*_*rth 11
使用quote
是安全的.我在你链接的页面上阅读了答案,我没有看到有人说这quote
是不安全的.我看到你关于使用"引号"的问题.是的,如果您只是在字符串周围加上引号,那就是不安全,例如:
q = "SELECT * FROM users where email = '#{params[:email]}'"
Run Code Online (Sandbox Code Playgroud)
但使用quote
(方法)很好:
q = "SELECT * FROM users where email = #{connection.quote(params[:email])}"
Run Code Online (Sandbox Code Playgroud)
你可以在控制台中玩游戏并尽力打破它,但我认为你不能:
2.3.3 :003 > ActiveRecord::Base.connection.quote("f''oo")
=> "'f''''oo'"
Run Code Online (Sandbox Code Playgroud)
如果你成功了,我确信Rails团队想知道(私下)!但正如您所看到的,该quote
方法不仅仅是在开头和结尾都贴上引号.
此外,由于您说您正在寻找权威引文,因此源代码本身中的注释表明引用用户输入是这些函数的预期目的:
# Quotes the column value to help prevent
# {SQL injection attacks}[http://en.wikipedia.org/wiki/SQL_injection].
def quote(value)
Run Code Online (Sandbox Code Playgroud)
# Quotes strings for use in SQL input.
def quote_string(s) #:nodoc:
Run Code Online (Sandbox Code Playgroud)
(注意我正在显示quote_string
注释,但您应该使用quote
,它会尝试找出数据类型并执行适当的操作.)
顺便说一句,这里有一个与你类似的问题,我在2014年得到了答案,还有一些替代方案:如何在rails中使用动态绑定执行原始更新sql
归档时间: |
|
查看次数: |
3556 次 |
最近记录: |