Ruby on Rails教程中的SQL插值

3

这是来自 MH 的《Ruby on Rails 教程》的代码:

def feed
    following_ids = "SELECT followed_id FROM relationships
                     WHERE  follower_id = :user_id"
    Micropost.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
end

这个SQL语句是否安全?因为很多人告诉我永远不要使用插值,而是使用转义代码(在这种情况下使用?)。所以这段代码是否安全?
2个回答

2

是的,这是安全的。

实际上没有插值:整个查询可以写成

Micropost.where("user_id IN (
     SELECT followed_id FROM relationships
      WHERE  follower_id = :user_id)
   OR user_id = :user_id", user_id: id)

为了更加清晰,第一个查询被提取到自己的变量中。

当插值字符串来自外部时,必须避免插值。这个字符串是在此处由你构造的,因此不存在 SQL 注入或类似风险。


示例

安全的,id 是确定的:

id = 42
"SELECT * FROM users WHERE users.id = #{id}"

不安全,params[:id] 来自外部可能存在危险:

"SELECT * FROM users WHERE users.id = #{params[:id]}"

1
这是安全的,因为字符串插值本身不是问题。只有当您无法控制插入查询的文本时,它才会导致安全漏洞。
在您的示例中,插入的字符串“following_ids”不是未知的用户输入,而是一个固定的SQL子查询。这不会导致安全问题。
但我同意这仍然不是一个好的示例,应该重构以使用作用域和Rails查询语法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接