Ruby on rails 避免SQL注入:范围中的原始SQL
我的模型中有以下范围:Ruby on rails 避免SQL注入:范围中的原始SQL,ruby-on-rails,postgresql,sql-injection,Ruby On Rails,Postgresql,Sql Injection,我的模型中有以下范围: scope :with_total_status, -> (date = Date.today) do select("agreements.*, ( SELECT json_agg(statuses) FROM ( SELECT ? AS calculated_status, SUM(?) AS total FROM agreement_install
scope :with_total_status, -> (date = Date.today) do
select("agreements.*, (
SELECT json_agg(statuses)
FROM (
SELECT
? AS calculated_status,
SUM(?) AS total
FROM agreement_installments
WHERE agreement_installments.agreement_id = agreements.id
GROUP BY calculated_status
) AS statuses
) agreement_status", "#{ AgreementInstallment.calculated_status_sql(date) }", "#{ AgreementInstallment.calculated_amount_remaining_or_paid(date) }")
end
为了避免SQL注入,我使用了?必要时在两个地方。它不工作,给我任何输出。但是,以下各项工作正常:
scope :with_total_status, -> (date = Date.today) do
select("agreements.*, (
SELECT json_agg(statuses)
FROM (
SELECT
#{AgreementInstallment.calculated_status_sql(date)} AS calculated_status,
SUM(#{AgreementInstallment.calculated_amount_remaining_or_paid(date)}) AS total
FROM agreement_installments
WHERE agreement_installments.agreement_id = agreements.id
GROUP BY calculated_status
) AS statuses
) agreement_status")
end
我不确定到底出了什么问题。您能告诉我避免SQL注入和获得正确输出的正确方向吗
这两个事实上都是案例陈述。def self.computed_status_sqldate,agreement_id=“agreements.id%Q{CASE WHEN agreement_installations.amount=从agreement_payments中选择sumamount,其中agreement_payments.agreement_installation_id=agreement_installations.id=agreement_installations,然后在------否则“future”END}结束时“ 在ActiveRecord中,select方法与where方法一样,不接受可能称为绑定变量的替换参数 您可以在下面构建子查询
SELECT sum(amount) FROM agreement_payments
WHERE agreement_payments.agreement_installment_id = agreement_installments.id
使用协议付款模式(如果有)
sum_query = AgreementPayment.select('sum(amount)').where(agreement_installment_id: agreement_id)
然后在生成的外部sql语句中使用sum_query.to_sql
执行此操作可能最终会将您构建的SQL注入最终SQL,因此它有风险,您需要小心。但是,您没有接受原始用户输入并将其注入最终SQL语句中。id值的输入通过这种方式得到正确的净化。很容易:要避免SQL注入,请不要注入。使用{...}完全在您的查询中。始终绑定为占位符。这是在计算列名吗?您是否有某种必须计算列名的架构?如果是,这是关系数据库故障。与其堆列,不如创建一个可以连接的关系表。这会使您的查询变得微不足道。因为占位符用于值不是标识符列名、表名……或SQL表达式;您的占位符可能最终会被单引号字符串替换。那么AgreementInstallation.Computed_status_sqldate和AgreementInstallation.Computed_amount_剩余_或_paiddate返回什么呢?它们实际上都是case语句。def self.calculated_status_sqldate,agreement_id=“agreements.id%Q{CASE WHEN agreement\u installations.amount=从协议付款中选择sumamount,其中agreement\u payments.agreement\u installations\u id=协议\u installations.id,然后在------否则“future”结束时“payment”}EndAgreementInstallation.Computed_status_sqldate和AgreementInstallation.Computed_amount_剩余_或_paiddate已在代码的其他几个位置使用。因此,为它们创建了单独的作用域。