【发布时间】:2021-07-26 02:16:09
【问题描述】:
我的模型中有以下范围:
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 注入并获得正确的输出吗?
【问题讨论】:
-
很简单:为了避免 SQL 注入,不要注入。在您的查询中完全使用
#{...}是无效的。始终绑定为占位符。 -
这是计算列名吗?您是否有某种必须计算列名的模式?如果是这样,那就是关系数据库故障。代替一堆列,创建一个关系表,你可以
JOIN。这使您的查询变得微不足道。 -
它不起作用,因为占位符用于值而不是标识符(列名,表名,...)或 SQL 表达式;您的占位符可能最终会被单引号字符串替换。那么
AgreementInstallment.calculated_status_sql(date)和AgreementInstallment.calculated_amount_remaining_or_paid(date)返回什么? -
这两个实际上都是案例陈述。 def self.calculated_status_sql(date, agreement_id = “agreements.id”) %Q{ CASE WHEN agreement_installments.amount = ( SELECT sum(amount) FROM agreement_payments WHERE agreement_payments.agreement_installment_id = agreement_installments.id ) THEN 'paid' WHEN ———— —— ELSE '未来' END } 结束
-
AgreementInstallment.calculated_status_sql(date) 和 AgreementInstallment.calculated_amount_remaining_or_paid(date) 已在代码的其他几个地方使用。因此,为它们创建了单独的范围。
标签: ruby-on-rails postgresql sql-injection