提问人:farha 提问时间:5/4/2021 最后编辑:farha 更新时间:5/4/2021 访问量:240
避免 SQL 注入:范围内的原始 SQL
Avoid SQL Injection: Raw SQL in scope
问:
我的模型中有以下范围:
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注入并获得正确的输出吗?
答:
0赞
Marlin Pierce
5/4/2021
#1
这两者实际上都是案例陈述。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 'future' END } end
在 ActiveRecord 中,该方法不像该方法那样采用替换参数(可能称为绑定变量)。select
where
您可以在下面构建子查询
SELECT sum(amount) FROM agreement_payments
WHERE agreement_payments.agreement_installment_id = agreement_installments.id
使用 AgreementPayment 模型(如果有)作为
sum_query = AgreementPayment.select('sum(amount)').where(agreement_installment_id: agreement_id)
然后在您构建的外部 SQL 语句中使用。sum_query.to_sql
这样做可能最终仍会将您构建的 SQL 注入到最终 SQL 中,因此它有风险,您需要小心。但是,您不会获取原始用户输入并将其注入到最终的 SQL 语句中。以这种方式正确审查 id 值的输入。
评论
#{...}
JOIN
AgreementInstallment.calculated_status_sql(date)
AgreementInstallment.calculated_amount_remaining_or_paid(date)