Python:连接MySQL并执行查询的最佳实践和最安全方法
在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'
)周围不能加单引号,因为驱动程序会自动处理这些引号。