使用有什么区别?清理ActiveRecord中的字段时的%和%?

时间:2013-10-17 21:41:36

标签: ruby-on-rails ruby rails-activerecord ruby-on-rails-2 sanitize

我对使用问号之间的差异感到困惑,例如

Foo.find(:all, :conditions => ['bar IN (?)', @dangerous])

并使用sprintf样式字段类型,例如

Bar.find(:all, :conditions => ['qux IN (%s)', @dangerous])

消毒投入。是否有任何安全优势,如果你知道你正在寻找一个数字 - 比如一个ID - 而不是一个字符串,在使用%d over?,或者你只是在字符串出现时要求一个大的讨厌错误?

在Rails 3和4中使用较新的.where语法是否会发生这种变化?

2 个答案:

答案 0 :(得分:1)

%s适用于字符串。主要区别在于%s不添加引号。来自ActiveRecord::QueryMethods.where

  

最后,您可以在模板中使用sprintf样式的%escapes。这个   与以前的方法略有不同;你是   负责确保模板中的值正确   引。这些值将传递给连接器以进行引用,但是   来电者有责任确保将它们括在引号中   结果SQL。引用后,使用相同的值插入值   作为Ruby核心方法Kernel::sprintf逃脱。

<强>示例:

User.where(["name = ? and email = ?", "Joe", "joe@example.com"])
# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';

User.where(["name = '%s' and email = '%s'", "Joe", "joe@example.com"])
# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';

更新

您正在传递数组。 %s似乎在参数上调用.to_s,因此这可能无法按预期工作:

User.where("name IN (%s)", ["foo", "bar"])
# SELECT * FROM users WHERE (name IN ([\"foo\", \"bar\"]))

User.where("name IN (?)", ["foo", "bar"])
# SELECT * FROM users WHERE (name IN ('foo','bar'))

对于简单查询,您可以使用散列表示法:

User.where(name: ["foo", "bar"])
# SELECT * FROM users WHERE name IN ('foo', 'bar')

答案 1 :(得分:1)

据我所知,%s只是在您的查询中插入了@dangerous.to_s恰好是什么,并且您对此负责。

例如,如果@dangerous是一个整数数组,那么你将得到一个SQL错误:

@dangerous = [1,2,3]
User.where("id IN (%s)", @dangerous)

将导致以下错误语法:

SELECT `users`.* FROM `users` WHERE (id IN ([1, 2, 3]))

,而:

User.where("id IN (?)", @dangerous)

生成正确的查询:

SELECT `users`.* FROM `users` WHERE (id IN (1,2,3))

因此,在我看来,除非你非常非常清楚你正在做什么,否则你应该让?运算符完成它的工作,特别是如果你不相信@dangerous的内容安全。