首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails清理活动记录查询中的用户输入

Rails清理活动记录查询中的用户输入
EN

Stack Overflow用户
提问于 2018-04-04 12:43:02
回答 3查看 1.4K关注 0票数 2

假设我有以下数据:

models/supplier.rb

代码语言:javascript
复制
| -- | ---------------- |
| id | name             |
| -- | ---------------- |
| 1  | John Doe's Store |
| 2  | Jane             |
| -- | ---------------- | 

我有以下查询,这些查询未能清理用户从搜索字段输入的内容:

代码语言:javascript
复制
@term = "John Doe's"

查询1

代码语言:javascript
复制
Supplier.order("case when name LIKE :term 1 else 2 end, name asc", term: "#{@term}%")

ArgumentError: Direction "one's%" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"]
from ~/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7/lib/active_record/relation/query_methods.rb:1113:in `block (2 levels) in validate_order_args'

查询2

易受SQL注入攻击

代码语言:javascript
复制
Supplier.order("case when name LIKE '#{@term}%' then 1 else 2 end, name ASC").first
  
Supplier Load (2.6ms)  SELECT  "suppliers".* FROM "suppliers"  ORDER BY case when name LIKE 'John Doe's%' then 1 else 2 end LIMIT 1
ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR:  syntax error at or near "s"
LINE 1: ...uppliers"  ORDER BY case when name LIKE 'John Doe's%' then 1..

查询3

对于没有' (特殊字符)的正常输入,它将获得成功,但是这个查询仍然容易受到SQL注入攻击。

代码语言:javascript
复制
@term = "John"

Supplier.order("case when name LIKE '#{@term}%' then 1 else 2 end, name ASC").first

#<Supplier:0x007fe4bfd8d758
 id: 188,
 name: "John Doe's Store">

我无法找到这个问题的解决方案,请帮助我以安全的方式完成这个查询。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-04-04 13:18:06

要转义输入,所需要的就是使用

代码语言:javascript
复制
ActiveRecord::Base.connection.quote(value)

这适用于所有类型,也是rails所使用的。

代码语言:javascript
复制
@term =  ActiveRecord::Base.connection.quote("John Doe's" + "%" )

Supplier.order("case when name LIKE #{@term} then 1 else 2 end, name ASC").first
票数 1
EN

Stack Overflow用户

发布于 2018-04-04 13:27:49

您可以使用基本连接引号,这将净化输入。

代码语言:javascript
复制
@term = "John Doe's"

like_value = ActiveRecord::Base.connection.quote(@term + '%') 

Supplier.order("case when name LIKE #{like_value} 1 else 2 end, name asc")

在这里读到..。

http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Quoting.html#method-i-quote

票数 1
EN

Stack Overflow用户

发布于 2022-09-30 15:06:20

Rails为此提供了sanitize_sql_like()

所以你的例子应该是这样的:

代码语言:javascript
复制
@term = "John Doe's"

like_value = sanitize_sql_like(@term + '%')

Supplier.order("case when name LIKE #{like_value} 1 else 2 end, name asc")

请参阅:like

编辑:

如果您需要在Controller中使用它,请如下所示:

代码语言:javascript
复制
ActiveRecord::Base::sanitize_sql_like()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49651339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档