Sql Rails会产生多种安全问题

Sql Rails会产生多种安全问题,sql,ruby-on-rails,Sql,Ruby On Rails,我正在创建一个范围块,它将按照 Letter.join(:people).where("people.lastname = ? OR people.lastname = ?", 'Carter', 'Testname') 但是,我希望能够使我的查询动态化,以便您可以发送任意数量的名称作为结果 Letter.find_person(['Carter', 'Testname']) 我已经找到了两种获得所需查询的方法,但我不确定这两种方法是否都非常安全。我想使用上面的问号语法,但我很难弄明白如何欺

我正在创建一个范围块,它将按照

Letter.join(:people).where("people.lastname = ? OR people.lastname = ?", 'Carter', 'Testname')
但是,我希望能够使我的查询动态化,以便您可以发送任意数量的名称作为结果

Letter.find_person(['Carter', 'Testname'])
我已经找到了两种获得所需查询的方法,但我不确定这两种方法是否都非常安全。我想使用上面的问号语法,但我很难弄明白如何欺骗它

1:

上述两种方法是否都符合Rails标准?似乎任何类型的字符串都可以传递到当前的查询中。有人对如何让Rails在运行查询之前检查查询有什么建议吗?

方法1。不安全

方法2。稳妥


方法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
的后续参数替换,并按顺序清除

> 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')
> 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')