>消毒
> 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
对于这种方法,我不知道清洁是否是上述的最佳选择,或者如果它在100%的情况下工作…(我仅使用Postgres)
class RawQuery def exec(prepared,*params) params.each_with_index do |p,i| prepared.gsub!("$#{i + 1}",ActiveRecord::Base.sanitize(p)) end ActiveRecord::Base.connection.exec_query(prepared) end end
简单的使用示例(通常不会这么简单,或者我只是使用AR):
RawQuery.new.exec(‘SELECT * FROM users WHERE name = $1’,params [:name])
此外,它似乎对2007年的代表进行了消毒.但根据this SO post的说法,简单地用单引号包装东西是不安全的…所以我不知道.
方法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
用同样的方法:
RawQuery.new.prepare(‘SELECT * FROM users WHERE name = $1’,params [:name])
我的应用程序总是远远超出了Rails能够采用sql方式的能力,我需要一个很好的lib,我可以在我所知道的所有项目中包含完全安全的内容.
解决方法
q = "SELECT * FROM users where email = '#{params[:email]}'"
但是使用quote(方法)很好:
q = "SELECT * FROM users where email = #{connection.quote(params[:email])}"
你可以在控制台中玩耍,尽力打破它,但我不认为你能够:
2.3.3 :003 > ActiveRecord::Base.connection.quote("f''oo") => "'f''''oo'"
如果你成功了,我肯定Rails团队想知道(私下)!但是您可以看到,引用方法不仅仅是在开始和结束时引用一个引号.
另外,由于你说你正在寻找一个权威的引文,源代码本身的意见表明引用用户输入是这些功能的预期目的:
# Quotes the column value to help prevent # {sql injection attacks}[http://en.wikipedia.org/wiki/sql_injection]. def quote(value)
# Quotes strings for use in sql input. def quote_string(s) #:nodoc:
(注意,我正在显示quote_string的评论,但你应该可以使用quote,它试图找出数据类型,并做适当的事情.)
顺便说一下,这里是一个类似的问题,你的答案,我在2014年和一些替代方案:How to execute a raw update sql with dynamic binding in rails