【问题标题】:Correct way to pass parameters containing string into Django Raw sql将包含字符串的参数传递到 Django Raw sql 的正确方法
【发布时间】:2015-02-27 22:18:14
【问题描述】:

我有一堆复杂的 sql 查询需要在 Django 上执行,而 Raw SQL 似乎是唯一的选择。我的参数是字符串,可以为空。为空的原因是我上面有条件语句,并且取决于需要执行正确的sql。但是当运行 ra sql 时,django 实际上会在 sql 中添加引号(我用它来表示字符串),因此它会引发错误。

我已简化查询以显示我面临的问题。以下查询在执行时会引发错误。

select_cond = ''
where_cond = 'id = 109'

qraw = Book.objects.raw(
        "\
        SELECT  id %s\
        FROM book\
        WHERE %s\
        ",
        [select_cond, where_cond]
)

错误是由于它被翻译如下。引号实际上进入了 sql,因此它不会执行。关于如何解决这个问题的任何想法?

 SELECT  id ''
 FROM book
 WHERE 'id = 109'
 ORDER BY id DESC;

【问题讨论】:

    标签: python mysql sql django django-models


    【解决方案1】:

    Django 为 raw 提供了一个 'params' argument,以避免潜在的 SQL 注入攻击。正如@alecxe 的示例所示,python 中的三引号是定义多行变量并避免任何反斜杠转义的好方法。这是“Django 方式”提出的安全解决方案:

    select_cond = condition
    where_cond = condition
    
    qraw = Book.objects.raw("""
        SELECT
            id, %(select_cond)s
        FROM
            book
        WHERE
            %(where_cond)s
        """, params={'select_cond': select_cond, 'where_cond': where_cond})
    

    只需将 condition 占位符替换为适当的值即可。

    【讨论】:

      【解决方案2】:

      这是 Django 使用的底层数据库驱动程序的默认行为。

      注意:我不确定尝试以这种方式构建查询的动机。

      只有当你信任你在查询中使用的 where 条件的来源时,才能通过字符串格式将它们放入查询中:

      qraw = Book.objects.raw("""
          SELECT 
              id, {select}
          FROM 
              book
          WHERE 
              {where}
          """.format(select=select_cond, where=where_cond)
      )
      

      同样,这样做并不安全,因为您实际上使它容易受到 SQL 注入的攻击。


      为了更安全,您可以预先解析将在查询中使用的 where 条件,并在字段值上手动调用 MySQLdb.escape_string(),例如:

      key, value = where_cond.split(' = ')
      value = MySQLdb.escape_string(value)
      where_cond = ' = '.join(key, value)
      

      【讨论】:

      • 我想指出它不安全 3 次不足以避免投票。
      猜你喜欢
      • 1970-01-01
      • 2012-12-02
      • 1970-01-01
      • 1970-01-01
      • 2016-03-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-06
      相关资源
      最近更新 更多