Подтвердить что ты не робот

Взломать список для использования в python MySQLDB IN

Я знаю, как сопоставить список со строкой:

foostring = ",".join( map(str, list_of_ids) )

И я знаю, что я могу использовать следующее, чтобы получить эту строку в разделе IN:

cursor.execute("DELETE FROM foo.bar WHERE baz IN ('%s')" % (foostring))

Мне нужно сделать то же самое БЕЗОПАСНО (избегая инъекции SQL) с помощью MySQLDB. В приведенном выше примере, поскольку foostring не передается в качестве аргумента для выполнения, он уязвим. Мне также нужно процитировать и выйти за пределы библиотеки mysql.

(Существует вопрос связанный вопрос SO, но ответы, перечисленные там, либо не работают для MySQLDB, либо уязвимы для SQL-инъекции.)

4b9b3361

Ответ 1

Используйте list_of_ids напрямую:

format_strings = ','.join(['%s'] * len(list_of_ids))
cursor.execute("DELETE FROM foo.bar WHERE baz IN (%s)" % format_strings,
                tuple(list_of_ids))

Таким образом, вы избегаете процитировать себя и избегаете всех видов SQL-инъекций.

Обратите внимание, что данные (list_of_ids) идут непосредственно в драйвер mysql, как параметр (не в тексте запроса), поэтому нет инъекции. Вы можете оставить любые символы, которые вы хотите в строке, не нужно удалять или указывать символы.

Ответ 2

Безболезненный MySQLdb execute('...WHERE name1 = %s AND name2 IN (%s)', value1, values2)

def execute(sql, *values):

    assert sql.count('%s') == len(values), (sql, values)
    placeholders = []
    new_values = []
    for value in values:
        if isinstance(value, (list, tuple)):
            placeholders.append(', '.join(['%s'] * len(value)))
            new_values.extend(value)
        else:
            placeholders.append('%s')
            new_values.append(value)
    sql = sql % tuple(placeholders)
    values = tuple(new_values)

    # ... cursor.execute(sql, values)

Ответ 3

list_of_ids = [ 1, 2, 3]
query = "select * from table where x in %s" % str(tuple(list_of_ids))
print query

Это может работать для некоторых прецедентов, если вы не хотите беспокоиться о методе, в котором вам нужно передать аргументы для завершения строки запроса и хотите вызвать только cursror.execute(query).

Другой способ:

"select * from table where x in (%s)" % ', '.join(str(id) for id in list_of_ids)

Ответ 4

Как предложил этот человек (Выполнение "SELECT... WHERE... IN..." using MySQLdb), быстрее использовать itertools. repeat(), чтобы создать список "% s", чем умножить список ['% s'] (и намного быстрее, чем использование map()), особенно для длинных списков.

in_p = ', '.join(itertools.repeat('%s', len(args)))

Эти тайм-ауты были выполнены с использованием Python 2.7.3 с процессором Intel Core i5 M 540 @2.53GHz × 4:

>>> timeit.timeit("repeat('%s', len(short_list))", 'from itertools import repeat; short_list = range(3)')
0.20310497283935547
>>> timeit.timeit("['%s'] * len(short_list)", 'short_list = range(3)')
0.263930082321167
>>> timeit.timeit("list(map(lambda x:'%s', short_list))", 'short_list = range(3)')
0.7543060779571533


>>> timeit.timeit("repeat('%s', len(long_list))", 'from itertools import repeat; long_list = range(1000)')
0.20342397689819336
>>> timeit.timeit("['%s'] * len(long_list)", 'long_list = range(1000)')
4.700995922088623
>>> timeit.timeit("list(map(lambda x:'%s', long_list))", 'long_list = range(1000)')
100.05319118499756

Ответ 5

Очень просто: просто используйте приведенную ниже формулу

rules_id = [ "9", "10" ]

sql1 = "SELECT * FROM attendance_rules_staff WHERE id in (" + ",".join(map (str, rules_id)) + ")"

",".join(map (str, rules_id))