Rails逃避用户输入?适当的安全措施?

时间:2014-08-24 23:53:39

标签: ruby-on-rails ruby security ruby-on-rails-4 rails-activerecord

以下内容之间有什么区别:

@user = User.find_by(["username = ?", params['username']])
User Load (0.5ms)  SELECT  "users".* FROM "users"  WHERE (username = '2YY') LIMIT 1

和此:

@user = User.find_by(username: params['username'])
User Load (0.5ms)  SELECT  "users".* FROM "users"  WHERE "users"."username" = '2YY' LIMIT 1

我看到的唯一区别是括号。这是如何摆脱糟糕的输入?我应该使用正则表达式来验证username吗?例如。用户名只能包含文字或数字,我应该在转到数据库之前对此进行验证,还是@user = User.find_by(["username = ?", params['username']])保护我?

而且,如果这两个查询具有相同的输出但第一个是安全的,那么第二个查询的重点是什么?

2 个答案:

答案 0 :(得分:1)

存在差异,但正确引用params['username']并非其中之一。在这两种情况下,ActiveRecord都会正确地转发用户名,因此您不必担心这一点。

一些差异:

  1. 第一种形式使用您编写的SQL代码段而不是将其留给AR来编写SQL。如果您需要AR并不真正理解的条件 - 例如函数调用(find_by(['lower(username) = ?', x])),布尔表达式(find_by('some_boolean_column and username = ?', x]))等 - 那么第一个表单允许您使用它们,而第二种形式更有限。
  2. 第二种形式包括表名("users")并引用列名("username")。如果您有JOIN并且需要消除列名称的歧义,那么包括表名是很有用的。如果列名称区分大小写或包含特殊字符,则引用列名称很有用。
  3. 使用像您一样的简单find_by时,上述问题很少出现。第二种形式:

    @user = User.find_by(username: params['username'])
    

    通常是首选的,并且被认为是更多Railsy,因为它隐藏了数据库交互的细节,并允许您假装SQL不存在。

答案 1 :(得分:0)

在这种情况下,两种类型的语法在功能上都是等效的,并且两者都将使用Rails的内置SQL清理,因此用户无法做任何令人讨厌的事情。代表您无需进行额外的清理,只需确保您没有将param插入/连接到SQL片段中。