0

正在从用户提供的未知行数的 CSV 文件中读取数据。我遍历行,而不是单独将每一行单独插入数据库(可能会损害大量插入的性能),我将这些值连接成一个字符串:

insert_values += ", (#{params[:quantity]}, #{'#{params[:name]}', '#{Time.now.to_s(:db)}')"

然后我构建完整的 sql 查询:

sql = "INSERT INTO `my_table` (`quantity`, `name`, `created_at`) VALUES"+insert_values

最后,我执行它:

ActiveRecord::Base.connection.execute(sql)

我想让数据免受恶意注入。做这个的最好方式是什么?

4

3 回答 3

1

如果您要这样做,那么您需要花时间使用 AR 的底层连接转义方法来转义进入数据库的每个字段。否则你只是自找麻烦。

或者...使用其他用于大量处理的东西,但仍为您处理转义... https://github.com/zdennis/activerecord-import

于 2012-12-07T18:09:07.940 回答
1

您可以考虑使用 MySQLLOAD DATA INFILE语法来插入 CSV 数据。它针对上传进行了优化,不需要您手动构建易于注入的查询字符串。

这是 MySQL 文档的链接:

http://dev.mysql.com/doc/refman/5.6/en/load-data.html

LOAD DATA [LOCAL] INFILE '/path/to/data.csv'
INTO table
FIELDS TERMINATED BY ',' ENCLOSED BY '' ESCAPED BY '\'
LINES TERMINATED BY '\n'

LOCAL如果应用服务器和数据库在不同的机器上,请注意使用。您可能需要根据 CSV 格式更改字段和行设置。

于 2012-12-07T18:12:24.217 回答
0

感谢所有有用的建议,这些建议使我走上了最后的道路。在阅读了另一篇文章后,我最终将我的字符串更改为一个值数组,以利用 Rails 内置方法 sanitize_sql_array 。

placeholders = []
insert_values = []

csvrow.each do |row|
  placeholders << (?,?,?)
  insert_values << params[:quantity] << #{params[:name]} << {Time.now.to_s(:db)
end

query_string = "INSERT INTO `my_table` (`quantity`, `name`, `created_at`) VALUES #{placeholders.join(", ")}"] + insert_values
sql = ActiveRecord::Base.send(:sanitize_sql_array, query_string)
ActiveRecord::Base.connection.execute(sql)
于 2012-12-07T20:30:25.767 回答