Rails 4 在 "Where" 方法中安全使用变量
Rails 4 safely using variables in "Where" method
我自己搜索了一个 Rails 4 应用程序。现在我需要为用户提供不同的列来进行搜索。我在视图的搜索表单中创建了一个下拉菜单,如下所示:
<%= form_tag manage_accounts_administrator_path, :method => 'get', :id => "search-form" do %>
<%= text_field_tag :search, params[:search], placeholder: 'Search Accounts' %>
<%= select_tag("search_criteria", options_for_select([['by account number', '1'],['by customer id', '2'],['by customer name (ex: Jane Doe)', '3']])) %>
<%= submit_tag "Search", :name => nil %>
<% end %>
然后在相应的控制器方法中,我这样做:
def manage_accounts
# criteria from the "Search by" select menu
if params[:search]
case (params[:search_criteria])
when 1
@criteria = id
when 2
@criteria = customer_id
when 3
@criteria = customer.firstname + ' ' + customer.lastname
end
@accounts = Account.where("#{@criteria} LIKE ?", "%#{params[:search]}%").page(params[:page]).per(15)
@table_heading = "Account Search Results"
else
@accounts = Account.order('id').page(params[:page]).per(15)
@table_heading = "Listing All Accounts"
end
respond_to do |format|
format.js
format.html {render 'manage_accounts'}
end
end
上面 case 块中 @criteria 变量的三个可能值表示 "Account" 模型的字段。如您所见,我期望发生的是使用 "where" 方法进行的查询。此语法错误,我收到错误消息:
ActiveRecord::StatementInvalid in Administrators#manage_accounts Mysql2::Error: You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to
use near 'LIKE '%722586388%')' at line 1: SELECT COUNT(*) FROM
accounts
WHERE ( LIKE '%722586388%')
显然我做错了。 如何像插入搜索参数那样插入@criteria 变量?错误告诉我的是变量被完全转义。我已经尝试(猜测)了几十种不同的标点符号组合,但都无济于事。我觉得如果我的语法正确的话这会起作用。
此外,我了解到这是一种不好的做法,因为它会使应用容易受到 SQL 注入攻击。 那么,我应该如何以安全的方式编写此语句?
谢谢
rails 4.1.8 MySQL2 gem 我是菜鸟
您忘记用引号将您的变量括起来。当执行到行时
@accounts = Account.where("#{@criteria} LIKE ?", "%#{params[:search]}%").page(params[:page]).per(15)
@criteria
仍将是 nil
。因此,activerecord 生成的 sql 将是 SELECT COUNT(*) FROM accounts WHERE ( LIKE '%722586388%')
而不是 SELECT COUNT(*) FROM accounts WHERE (id LIKE '%722586388%')
,例如
所以在你的情况下,你将不得不这样做:
if params[:search]
case (params[:search_criteria])
when 1
@criteria = 'id'
when 2
@criteria = 'customer_id'
when 3
@criteria = 'customer.firstname'
end
if params[:search]
case (params[:search_criteria])
when 1
@criteria = "id"
when 2
#assuming you have a customer_id column in your accounts table
@criteria = "customer_id"
when 3
#assuming you have a customer_name column in your accounts table
@criteria = "customer_name"
end
我自己搜索了一个 Rails 4 应用程序。现在我需要为用户提供不同的列来进行搜索。我在视图的搜索表单中创建了一个下拉菜单,如下所示:
<%= form_tag manage_accounts_administrator_path, :method => 'get', :id => "search-form" do %>
<%= text_field_tag :search, params[:search], placeholder: 'Search Accounts' %>
<%= select_tag("search_criteria", options_for_select([['by account number', '1'],['by customer id', '2'],['by customer name (ex: Jane Doe)', '3']])) %>
<%= submit_tag "Search", :name => nil %>
<% end %>
然后在相应的控制器方法中,我这样做:
def manage_accounts
# criteria from the "Search by" select menu
if params[:search]
case (params[:search_criteria])
when 1
@criteria = id
when 2
@criteria = customer_id
when 3
@criteria = customer.firstname + ' ' + customer.lastname
end
@accounts = Account.where("#{@criteria} LIKE ?", "%#{params[:search]}%").page(params[:page]).per(15)
@table_heading = "Account Search Results"
else
@accounts = Account.order('id').page(params[:page]).per(15)
@table_heading = "Listing All Accounts"
end
respond_to do |format|
format.js
format.html {render 'manage_accounts'}
end
end
上面 case 块中 @criteria 变量的三个可能值表示 "Account" 模型的字段。如您所见,我期望发生的是使用 "where" 方法进行的查询。此语法错误,我收到错误消息:
ActiveRecord::StatementInvalid in Administrators#manage_accounts Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIKE '%722586388%')' at line 1: SELECT COUNT(*) FROM
accounts
WHERE ( LIKE '%722586388%')
显然我做错了。 如何像插入搜索参数那样插入@criteria 变量?错误告诉我的是变量被完全转义。我已经尝试(猜测)了几十种不同的标点符号组合,但都无济于事。我觉得如果我的语法正确的话这会起作用。
此外,我了解到这是一种不好的做法,因为它会使应用容易受到 SQL 注入攻击。 那么,我应该如何以安全的方式编写此语句?
谢谢
rails 4.1.8 MySQL2 gem 我是菜鸟
您忘记用引号将您的变量括起来。当执行到行时
@accounts = Account.where("#{@criteria} LIKE ?", "%#{params[:search]}%").page(params[:page]).per(15)
@criteria
仍将是 nil
。因此,activerecord 生成的 sql 将是 SELECT COUNT(*) FROM accounts WHERE ( LIKE '%722586388%')
而不是 SELECT COUNT(*) FROM accounts WHERE (id LIKE '%722586388%')
,例如
所以在你的情况下,你将不得不这样做:
if params[:search]
case (params[:search_criteria])
when 1
@criteria = 'id'
when 2
@criteria = 'customer_id'
when 3
@criteria = 'customer.firstname'
end
if params[:search]
case (params[:search_criteria])
when 1
@criteria = "id"
when 2
#assuming you have a customer_id column in your accounts table
@criteria = "customer_id"
when 3
#assuming you have a customer_name column in your accounts table
@criteria = "customer_name"
end