我正在进行手动的join
,并且需要将参数传递给其ON
子句:
Foo.joins("LEFT OUTER JOIN bars ON foos.id = bars.foo_id AND bars.baz = #{baz}")
有没有一种方法可以将baz
作为参数传递,以避免潜在的注入问题?有一个sanitize_sql_array
的方法,但我不确定如何在这种情况下使用它。
注意:我不能使用where
,因为它不一样。
我正在进行手动的join
,并且需要将参数传递给其ON
子句:
Foo.joins("LEFT OUTER JOIN bars ON foos.id = bars.foo_id AND bars.baz = #{baz}")
有没有一种方法可以将baz
作为参数传递,以避免潜在的注入问题?有一个sanitize_sql_array
的方法,但我不确定如何在这种情况下使用它。
注意:我不能使用where
,因为它不一样。
使用sanitize_sql_array,代码应该是这样的:
# Warning: sanitize_sql_array is a protected class method, be aware of that to properly use it in your code
ar = ["LEFT OUTER JOIN bars ON foos.id = bars.foo_id AND bars.baz = %s", baz]
# Within a class method in foo model:
sanitized_sql = sanitize_sql_array(ar)
Foo.joins(sanitized_sql)
尝试过了,它起作用了。
sanitize_sql_array
,例如 Foo.sanitize_sql_array
。 - Joshua Pintersanitize_sql_array
就可以在类方法中使用它,但在实例方法中使用时,你需要从类中调用它,如 Foo.sanitize_sql_array
。感谢你为我和其他人澄清了这一点。 :) - Joshua PinterActiveRecord::Base
类来访问它:
ActiveRecord::Base.sanitize_sql_array(['INNER JOIN foo on bar = ?', 123])
- zinovyevActive record 模型有 sanitize
类方法,所以你可以这样做:
Foo.joins("LEFT OUTER JOIN bars ON foos.id = bars.foo_id AND bars.baz = #{Foo.sanitize(baz)}")
自rails 5.1版本开始,它已被移除,请改用ActiveRecord::Base.connection.quote()
sanitize
不再是公共 API 的一部分,它在 Rails 5.1 中被移除了(请参阅https://github.com/rails/rails/issues/28947中的讨论和解决方法)。 - nerfologistbaz = "i am a baz"
foos = Arel::Table.new('foos') # or Foo.arel_table, if this is an AR model
bars = Arel::Table.new('bars')
join = foos.outer_join(bars).on(
foos[:id].eq(bars[:foo_id]),
bars[:baz].eq(baz))
puts join.to_sql
SELECT FROM "foos"
LEFT OUTER JOIN "bars" ON
"foos"."id" = "bars"."foo_id"
AND "bars"."baz" = 'i am a baz'
Foo.joins(join.join_sources)
Foo.arel_table
可以在代码中不使用表名。 - Mark Huk我认为你应该尝试这样做:
Foo.joins("LEFT OUTER JOIN bars ON foo.id = bars.foo_id AND bars.baz = ?", baz)
带更多参数:
Foo.joins("LEFT OUTER JOIN bars ON foo.id = ? AND bars.baz = ? AND ...", foo, baz, etc...)
baz
不会被解释为参数值,而是作为另一个连接模型。你可以自己尝试一下。https://github.com/rails/rails/blob/9b67cb3d394692aa7feb7510aab0871e557d3dd0/activerecord/lib/active_record/relation/query_methods.rb#L1036 - Mladen Jablanović如果您传递值的哈希,AR 将保护您免受 SQL 注入攻击,这样您就可以放心使用:
Foo.joins("LEFT OUTER JOIN bars ON foo.id = bars.foo_id").where(bars: {baz: baz})
在编写 SQL 语句时,不要使用容易受到 SQL 注入攻击的行字符串。
JOIN
子句中与放在WHERE
子句中是不同的。详情请见http://sqlfiddle.com/#!9/c827b7/5。 - Old Pro
baz
是一个变量,保存着一个字符串字面值或者一个数字,例如。它不是另一个模型,而是一个我想要传递给外连接ON条件的值。 - Mladen Jablanović