Rails生成多个条件安全问题

时间:2015-01-16 17:09:32

标签: sql ruby-on-rails

我正在创建一个范围块,它将生成

的内容
Letter.join(:people).where("people.lastname = ? OR people.lastname = ?", 'Carter', 'Testname')

我希望能够使我的查询动态化,因此您可以发送任意数量的名称作为结果拉入

Letter.find_person(['Carter', 'Testname'])

我已经找到了两种方法来获得所需的查询,但我不确定它们中的任何一种都非常安全。我想使用上面的问号语法,但我无法弄清楚如何使用它。

1:

peopleArray.each_with_index do |person, index|
  # first person in array does not need an "OR" at the front
  the_or = index == 0 ? "" : " OR "
  # TODO make this statement more secure
  whereClause << "#{the_or}people.lastname = '#{person}'"
end
joins(:people).where(whereClause).length

2:

joins(:people).where({"people.lastname" => array})

Rails标准是否保证上述任何一种方法都是安全的?似乎现在任何类型的字符串都可以传递到查询中。有没有人有任何关于如何在运行之前让Rails检查查询的建议?

2 个答案:

答案 0 :(得分:2)

答案 1 :(得分:1)

方法2是安全的,因为Rails在从哈希构造子句时会自动清理。

Rails不会清理你为方法1传递的子句。(实际上,Rails无法确定字符串whereClause的哪个部分是用户输入需要消毒并且是硬编码的,因此正是你的意图。)

如果您将控制台设置为从ActiveRecord活动输出SQL,则可以看到此信息:

> User.where(first_name: "first'name", last_name: "last'name")

User Load (166.9ms)  SELECT `users`.* FROM `users`  WHERE `users`.`first_name` = 'first\'name' AND `users`.`last_name` = 'last\'name'

> User.where("first_name = 'first'name' AND last_name = 'last'name'")

User Load (0.2ms)  SELECT `users`.* FROM `users`  WHERE (first_name = 'first'name' AND last_name = 'last'name')

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'name' AND last_name = 'last'name')' at line 1: SELECT `users`.* FROM `users`  WHERE (first_name = 'first'name' AND last_name = 'last'name')

要回答你的第二个问题(如何使方法1安全),你应该这样做:

> User.where("first_name = ? AND last_name = ?", "first'name", "last'name")

User Load (165.8ms)  SELECT `users`.* FROM `users`  WHERE (first_name = 'first\'name' AND last_name = 'last\'name')

正如您所见,where的后续参数会在结果查询中替换问号,并按顺序进行清理。