Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 避免SQL注入:范围中的原始SQL_Ruby On Rails_Postgresql_Sql Injection - Fatal编程技术网

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已在代码的其他几个位置使用。因此,为它们创建了单独的作用域。