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

74 投票
2 回答
54198 浏览
提问于 2025-04-17 05:11

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

但是,我不知道应该如何运行查询,以防止其他用户(网页客户端)操控的变量被注入。我以前自己写过转义函数,但显然这样做是不推荐的。

我应该使用什么,怎么用,才能在Python中安全地查询和插入MySQL数据库,而不冒SQL注入的风险?

2 个回答

88

作为对Bruno回答的补充,你的MySQL客户端库可能支持几种不同的格式来指定命名参数。根据PEP 249 (DB-API),你可以这样写你的查询:

'qmark'

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

'numeric'

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

'named'

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

'format'

>>> 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'

以上任何选项都应该能正确处理你可能不安全的数据。正如Bruno所提到的,请不要尝试自己插入参数。常用的客户端库在处理数据方面要比我们这些普通人强得多。

103

为了避免注入攻击,使用 execute 方法时,把每个变量的位置用 %s 替换,然后把实际的值通过列表或元组作为 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')周围不能加单引号,因为驱动程序会自动处理这些引号。

撰写回答