我的python代码中有以下查询:
query = """SELECT id
FROM dings_archive
WHERE doorbot_id IN {doorbot_ids};
"""
query = query.format(doorbot_ids=tuple(doorbot_ids))
doorbot_ids
的类型为List[int]
,当我的数组只包含1个元素时,我遇到了问题,因为在query.format
后我有以下查询:
SELECT id
FROM dings_archive
WHERE doorbot_id IN (123,);
如你所见,我有一个错误,因为最后有逗号,
。如何解决这个问题?
答案 0 :(得分:0)
为了防止SQL注入,你不应该使用自动将元组转换为字符串(你当前正在做什么),或者在将值传递给驱动程序之前手动加入值列表。
您目前正在利用一个元组转换为字符串产生合理结果的事实:
str((1, 2))
# '(1, 2)'
但正如您所注意到的,单个元素元组会产生语法错误:
str((1, ))
# '(1,)'
有些人建议手动连接列表:
','.join((1, 2))
# '1,2'
也适用于单个元素元组:
','.join((1,))
# '1'
然而这打开了SQL注入的大门,因为逗号实际上是MySQL的控制语句,而不仅仅是一个值。因此,如果有人能够在您的列表中隐藏控制语句,他们可以注入代码:
','.join((1,'1) OR 1=1 --'))
# '1,1) OR 1=1 --'
为了安全抵御此类攻击,您应准备一个查询,其占位符与ID列表中的元素完全相同:
doorbot_ids = [1, 2]
query = "SELECT id FROM dings_archive WHERE doorbot_id IN ({});".format(','.join(['%s'] * len(doorbot_ids)))
这将返回一个新查询,其中包含所需的几个占位符:
'SELECT id FROM dings_archive WHERE doorbot_id IN (%s,%s);'
然后每个占位符都填充一个值:
query = cursor.execute(query, doorbot_ids)
答案 1 :(得分:0)
不要将列表转换为元组,直接使用它:
query = """SELECT id
FROM dings_archive
WHERE doorbot_id = any(%s);
"""
...
cursor.mogrify(query, (doorbot_ids,))