Python: 连接到 MySQL 并执行查询的最佳实践和最安全的方式

在 MySQL 上运行查询最安全的方法是什么?我知道 MySQL 和 SQL 注入的危险性。

但是,我不知道应该如何运行查询来防止注入其他用户(webclient)可以操作的变量。我过去常常编写自己的转义函数,但显然这是“未完成的”。

我应该使用什么以及如何使用它通过 python 安全地查询和插入 MySQL 数据库,而不会有 MySQL 注入的风险?

50273 次浏览

为了避免注入,使用 execute%s代替每个变量,然后通过 list 或 tuple 传递值作为 execute的第二个参数。这是 例子从文件:

c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < %s""", (max_price,))

注意,这里使用的是 逗号,而不是 %(这将是一个直接的字符串替换,而不是转义):

c.execute("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < %s""" % (max_price,))

此外,如果参数是字符串(驱动程序提供了这些参数) ,则不能在位置持有者('%s')周围使用单引号。

作为 Bruno 答案的扩展,您的 MySQL 客户端库可能支持指定命名参数的几种不同格式中的任何一种。在 PEP 249(DB-API)中,您可以编写如下查询:

“ qmark”

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = ?", (lumberjack,))

“数字”

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = :1", (lumberjack,))

名字

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = :jack", {'jack': lumberjack})

格式

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = %s", (lumberjack,))

‘ pyformat’

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = %(jack)s", {'jack': lumberjack})

通过查看 paramstyle模块级变量,您可以看到您的客户端库支持哪些内容:

>>> clientlibrary.paramstyle
'pyformat'

在处理可能不安全的数据时,上面的任何选项都应该是正确的。正如布鲁诺指出的那样,请永远不要尝试自己插入参数。常用的客户端库在正确处理数据方面比我们这些凡人要好得多。